uva11478

题意:

题目要求求得一个最大的最小权值,任意选择一个点,以这个点为终点的边减去一个数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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值