uva11478

来源:互联网 发布:明基wit护眼灯 知乎 编辑:程序博客网 时间:2024/05/22 08:08

题意:

题目要求求得一个最大的最小权值,任意选择一个点,以这个点为终点的边减去一个数d,以这个点为起点的边江上d,那么对于一个点,可总和与该点的操作为d[a],二分枚举最小的权值x.假设边为a->b,那么对于a->b的边就有x<=w[a,b]+d[a]-d[b],那么就能推出d[b]<=d[a]+w[a,b]-x;

那么把w[a,b]-x当成整体的化形式就很熟悉了,这是一个差数约分系统,只要没有负环就是有解

那么要判断是不是无穷大只要最小权值是原先的最大值即可,判断是不是无解只要原先的最小权值不能得到正环,也就是没有任何操作使得x==最小权值成立

建立超级原点是确保原点与每个点都连接

代码:

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>using namespace std;const int maxn = 505;const int INF = 0x3f3f3f3f;int n, m;struct edge {int u,v, w;int next;}e[2705+1000];int head[maxn];int num;int d[maxn];void add(int a, int b, int c) {e[num].u = a;e[num].v = b;e[num].w = c;e[num].next = head[a];head[a] = num++;}bool bell(int k) {for(int i=1; i<=n; i++) d[i] = INF;d[0] = 0;for(int q=0; q<n; q++)for(int i=0; i<num; i++) {int a = e[i].u, b = e[i].v;if(d[a] != INF && d[b] > d[a]+e[i].w-k) {d[b] = d[a] + e[i].w - k;}}for(int i=0; i<num; i++) {if(d[e[i].u] != INF && d[e[i].v] > d[e[i].u]+e[i].w-k)return false;}return true;}int main() {int a, b, c;while(scanf("%d%d", &n, &m) != EOF) {num = 0;memset(head, -1, sizeof(head));int l, r = 0;for(int i=1; i<=n; i++) add(0, i, 0);for(int i=0; i<m; i++) {scanf("%d%d%d", &a, &b, &c);add(a, b, c);r = max(r, c);}l = 1;if(bell(r)) {  puts("Infinite");  continue;  }  else if(!bell(l)) {  puts("No Solution");  continue;  }  int ans=l++;  while(l<r) {int mid = (l+r)/2;if(bell(mid)) {l = mid+1;ans = mid;}else r = mid; }printf("%d\n",ans);}return 0;}



0 0