Intervals(poj 1201)
原题链接
题目类型:差分系统
解题思路:
假设s[i]代表的是从0到i-1所能选择的点的个数,则对于ai,bi,ci有以下式子成立s[bi+1]-s[ai]>=ci
同时,1>=s[i+1]-s[i]>=0
需要注意的是,本题要求求解s[i]的最小值。
我们知道,对于xa-xb<=xc,xa-x0<=w,求得的解是满足条件xi<=w的最大值,若设置w为0,那么xi即为最大的负数,即最小的正数。这也是本题的要求。
为此,将上述不等式转化为:
s[ai]<=-ci+s[bi+1]
s[i+1]<=1+s[i]
s[i]<=0+s[i+1]
s[i]<=0+s[x0]
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define ABMAX 55000
#define INF 0x3f3f3f3f
int h[ABMAX];
struct edge {
int from, to, nxt, w;
};
vector<edge> E;
int num = 0;
int n, ai, bi, ci;
int dst[ABMAX], inq[ABMAX];
void addline(int from, int to, int weight) {
edge cur;
cur.from = from, cur.to = to, cur.w = weight, cur.nxt = h[from];
h[from] = E.size();
E.push_back(cur);
}
void spfa(int s) {
queue<int> Q;
memset(dst, INF, sizeof(dst));
memset(inq, 0, sizeof(inq));
dst[s] = 0, inq[s] = 1;
Q.push(s);
while (!Q.empty()) {
int x = Q.front();
Q.pop();
for (int i = h[x]; i != -1; i = E[i].nxt) {
int y = E[i].to;
if (dst[y] > dst[x] + E[i].w) {
dst[y] = dst[x] + E[i].w;
if (!inq[y]) Q.push(y);
}
}
}
}
int main() {
cin >> n;
memset(h, -1, sizeof(h));
for (int i = 0; i < n; i++) {
cin >> ai >> bi >> ci;
if (bi + 1 > num) num = bi + 1;
addline(bi + 1, ai, -ci);
}
for (int i = 0; i <= num; i++) {
addline(num + 1, i, 0);
if (i != num) {
addline(i + 1, i, 0);
addline(i, i + 1, 1);
}
}
spfa(num + 1);
cout << -dst[0] << endl;
}
需要注意的是,最后不应该输出dst[num],而应该输出dst[0]
//2022.6.10更新
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
#define ABMAX 55000
#define INF 0x3f
int h[ABMAX];
struct edge {
int from, to, nxt, w;
};
vector<edge> E;
int num = 0;
int n, ai, bi, ci;
int dst[ABMAX], inq[ABMAX];
void addline(int from, int to, int weight) {
edge cur;
cur.from = from, cur.to = to, cur.w = weight, cur.nxt = h[from];
h[from] = E.size();
E.push_back(cur);
}
void spfa(int s) {
queue<int> Q;
memset(dst, -INF, sizeof(dst));
memset(inq, 0, sizeof(inq));
dst[s] = 0, inq[s] = 1;
Q.push(s);
while (!Q.empty()) {
int x = Q.front();
Q.pop();
inq[x] = 0;
//cout << Q.size() << endl;
for (int i = h[x]; i != -1; i = E[i].nxt) {
int y = E[i].to;
if (dst[y] < dst[x] + E[i].w) {
dst[y] = dst[x] + E[i].w;
if (!inq[y]) {
inq[y] = 1;
Q.push(y);
}
}
}
}
}
int main() {
cin >> n;
memset(h, -1, sizeof(h));
for (int i = 0; i < n; i++) {
cin >> ai >> bi >> ci;
if (bi > num) num = bi;
addline(ai-1, bi, ci);
}
for (int i = 1; i <= num; i++) {
//addline(0, i, 0);
addline(i - 1, i, 0);
addline(i, i - 1, -1);
}
spfa(0);
cout << dst[num] << endl;
}
Is the Information Reliable?(poj 2983)
原题链接
解题思路:对于等于号,例如a-b=c,建立a-b>=c和a-b<=c两个不等式。转化为差分系统之后,使用spfa判定负权环的方式进行是否存在解的判断(松弛次数超过点数)。
//tle
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define NMAX 1100
#define INF 0x3f3f3f3f
int h[NMAX];
struct edge {
int from, to, nxt, w;
};
vector<edge> E;
int N, M;
int dst[NMAX], inq[NMAX], out[NMAX];
void addline(int from, int to, int weight) {
edge cur;
cur.from = from, cur.to = to, cur.w = weight, cur.nxt = h[from];
h[from] = E.size();
E.push_back(cur);
}
int spfa(int s) {
queue<int> Q;
memset(dst, INF, sizeof(dst));
memset(inq, 0, sizeof(inq));
memset(out, 0, sizeof(out));
dst[s] = 0, inq[s] = 1;
Q.push(s);
while (!Q.empty()) {
int x = Q.front();
Q.pop();
for (int i = h[x]; i != -1; i = E[i].nxt) {
int y = E[i].to;
if (dst[y] > dst[x] + E[i].w) {
out[y]++;
if (out[x] >= N+1) {
return 0;
}
dst[y] = dst[x] + E[i].w;
if (!inq[y]) Q.push(y);
}
}
}
return 1;
}
int main() {
while (scanf_s("%d %d",&N,&M)==2) {
memset(h, -1, sizeof(h));
getchar();
E.clear();
//if (!N && !M) break;
for (int i = 0; i < M; i++) {
char c = getchar();
if (c == 'P') {
int a, b, c;
cin >> a >> b >> c;
addline(a, b, c);
addline(b, a, -c);
getchar();
}
else if (c == 'V') {
int a, b;
cin >> a >> b;
addline(b, a, -1);
getchar();
}
else cout << "WA";
}
for (int i = 1; i <= N; i++) {
addline(0, i, 0);
}
if (spfa(0))cout << "Reliable" << endl;
else cout << "Unreliable" << endl;
}
}