- 题目大意
可以给每个点的入边加一个值和出边加一个值,问最小的边权最大是多少。
- 解题思路
根据题目的描述,可以列出一个不等式d(a,b) +x(a)-x(b)>=m,移项可得x(b)-x(a)<=d(a,b)-m正好满足差分约束的形式。所有的边就对应着一个差分约束系统。差分约束有解的充要条件是不存在负环。然后利用SPFA和二分法来查找即可。
- 代码
#include<cstdio> #include<algorithm> #include<queue> #include<vector> #include<cstring> using namespace std; const int N = 1e3; const int M = 1e6 + 5; const int INF = 0x3f3f3f; int n, m; struct edge { int v, next, w; }e[M * 2]; int head[N], cnt; int d[N]; int inq[N]; int cn[N]; void addedge(int u, int v, int c) { e[cnt].w = c; e[cnt].v = v; e[cnt].next = head[u]; head[u] = cnt++; } bool SPFA(int s) { memset(d, INF, sizeof(d)); memset(inq, 0, sizeof(inq)); memset(cn, 0, sizeof(cn)); queue<int> Q; Q.push(s); d[s] = 0; inq[s] = 1; cn[s]++; while (Q.size()) { int u = Q.front(); Q.pop(); inq[u] = 0; for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; int w = e[i].w; if (d[v] > d[u] + w) { d[v] = d[u] + w; if (!inq[v]) { Q.push(v); inq[v] = 1; if (++cn[v] >= n+1) return false; } } } } return true; } bool check(int x) { bool vis = true; for (int i = 0; i <= n; i++) { for (int j = head[i]; j != -1; j = e[j].next) e[j].w -= x; } if (!SPFA(0)) vis = false; for (int i = 0; i <= n; i++) { for (int j = head[i]; j != -1; j = e[j].next) e[j].w += x; } return vis; } int main() { int a, b, c; while(~scanf("%d%d", &n, &m)) { int sum = 1; cnt = 0; memset(head, -1, sizeof(head)); int l = 1, r = -INF, mid; for (int i = 0; i < m; i++) { scanf("%d%d%d", &a, &b, &c); addedge(a, b, c); r = max(r, c); } for (int i = 1; i <= n; i++) addedge(0, i, 0); if (check(r + 1)) { printf("Infinite "); continue; } else if (!check(1)) { printf("No Solution "); continue; } else { while (r - l >= 0) { mid = (r + l) / 2; if (check(mid)) { l = mid + 1; sum = mid; } else { r = mid - 1; } } } printf("%d ", sum); } return 0; }