UVA - 11478 Halum 二分+差分约束

时间:2023-03-09 23:35:25
UVA - 11478 Halum 二分+差分约束

题目链接:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34651

题意:

给定一个有向图,每一条边都有一个权值,每次你可以选择一个节点v和一个整数d,把所有以v结尾的边权值减小d,把所有以v为起点的边的权值增加d,最后要让所有边权的最小值大于0且尽量大。

题解:

最小值最大,可以用二分,这样可以得到一个差分约束系统,然后每次都用最短路跑。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std; const int maxn = ;
const int maxm = ; struct Edge {
int v, w;
Edge(int v, int w) :v(v), w(w) {}
Edge() {}
}; vector<Edge> egs;
vector<int> G[maxn];
int tot = ;
int n, m; void addEdge(int u, int v, int w) {
egs.push_back(Edge(v, w));
tot = egs.size();
G[u].push_back(tot - );
} bool inq[maxn];
int d[maxn];
int cnt[maxn];
bool spfa(int x) {
bool ret = true; for (int i = ; i < n; i++) {
for (int j = ; j < G[i].size(); j++) {
Edge& e = egs[G[i][j]];
e.w -= x;
}
}
memset(inq, , sizeof(inq));
memset(cnt, , sizeof(cnt));
memset(d, 0x3f, sizeof(d)); queue<int> Q;
d[] = ; inq[] = true; Q.push();
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = false;
for (int i = ; i < G[u].size(); i++) {
Edge& e = egs[G[u][i]];
if (d[e.v] > d[u] + e.w) {
d[e.v] = d[u] + e.w;
if (!inq[e.v]) {
Q.push(e.v); inq[e.v] = true;
if (++cnt[e.v] > n) {
ret = false; break;
}
}
}
}
if (ret == false) break;
//printf("u:%d\nx:%d\n", u,x);
//printf("in circle\n");
} for (int i = ; i < n; i++) {
for (int j = ; j < G[i].size(); j++) {
Edge& e = egs[G[i][j]];
e.w += x;
}
} return ret;
} void init() {
for (int i = ; i < n; i++) G[i].clear();
egs.clear();
} int main() {
while (scanf("%d%d", &n, &m) == && n) {
n++;
init();
int l = , r = -;
for (int i = ; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
r = max(r, w);
addEdge(u, v, w);
}
for (int i = ; i < n; i++) {
addEdge(, i, );
}
r++;
if (!spfa()) {
printf("No Solution\n");
}
else if (spfa(r)) {
printf("Infinite\n");
}
else {
while (l + < r) {
int mid = l + (r - l) / ;
if (spfa(mid)) l = mid;
else r = mid;
//printf("here!\n");
}
printf("%d\n", l);
} }
return ;
} /*
1
2 10
1
2 -10
3
2 4
3 2
1 5
5
3 4
2 5
4 2
1 0
2 -1
*/