BZOJ1202/HNOI2005 狡猾的商人 差分约束+最短路

版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82805306

传送门

题目一看就是差分约束系统。。。不知道为什么有人会想到最短路
我用了一种奇奇怪怪的做法:最短路。
以天数为点,以花费来建图
首先发现如果一个账本是正确无误的,则每条到该点的路径中,长度都应该是相等的
所以只要判断到每个点的最长路和最短路是否相等就行了
于是看到数据范围,floyd过不了,直接一个多源SPFA23333
不管了反正过了.jpg 不过应该有更好的做法的
细节:因为题目给出条件时说的是从 s s 月初到 t t 月末的收支情况,所以看作是 s s 月初到 t + 1 t+1 月初的收入,就不存在自环了

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 105;
const int MAXM = 1001;
const LL INF = 1e15;

int fir[MAXN], nxt[MAXM << 1], to[MAXM << 1], len[MAXM << 1], cnt;
LL Maxdis[MAXN][MAXN], Mindis[MAXN][MAXN];
LL dis[MAXN][MAXN];
int vis[MAXN];

inline int read(){
	int k = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
	return k * f;
}

inline void add_edge(int a, int b, int l){
	len[cnt] = l;
	to[cnt] = b;
	nxt[cnt] = fir[a];
	fir[a] = cnt++;
}

void SPFA1(int x){
	queue<int> q; q.push(x);
	memset(vis, 0, sizeof(vis)); vis[x] = true;
	Maxdis[x][x] = 0;
	int u;
	while(!q.empty()){
		u = q.front(); q.pop(); vis[u] = false;
		for(int i = fir[u]; i != -1; i = nxt[i]){
			int v = to[i];
			if(Maxdis[x][v] < Maxdis[x][u] + len[i]){
				Maxdis[x][v] = Maxdis[x][u] + len[i];
				if(!vis[v]){
					q.push(v);
					vis[v] = true;
				}
			}
		}
	}
}

void SPFA2(int x){
	queue<int> q; q.push(x);
	memset(vis, 0, sizeof(vis)); vis[x] = true;
	Mindis[x][x] = 0;
	int u;
	while(!q.empty()){
		u = q.front(); q.pop(); vis[u] = false;
		for(int i = fir[u]; i != -1; i = nxt[i]){
			int v = to[i];
			if(Mindis[x][v] > Mindis[x][u] + len[i]){
				Mindis[x][v] = Mindis[x][u] + len[i];
				if(!vis[v]){
					q.push(v);
					vis[v] = true;
				}
			}
		}
	}
}

int main(){
	int T = read();
	while(T--){
		memset(fir, -1, sizeof(fir)); cnt = 0;
//		memset(dis, false, sizeof(dis));
		memset(dis, 0x3f, sizeof(dis));
		memset(Maxdis, 0xcf, sizeof(Maxdis));
		memset(Mindis, 0x3f, sizeof(Mindis));
		int n = read() + 1, m = read();
//		for(int i = 1; i <= n + 1; i++){
//			dis[i][i] = true;
//			Maxdis[i][i] = Mindis[i][i] = 0;
//		}
		bool Flag = false;
		for(int i = 1; i <= m; i++){
			int a = read(), b = read() + 1, l = read();
			if(Mindis[a][b] < INF && Mindis[a][b] != l) Flag = true;
			if(Mindis[a][b] >= INF){
				add_edge(a, b, l);
			}
//			if(Mindis[a][b] < INF) if(Mindis[a][b] != l) Flag = true;
//			if(Mindis[a][b] >= INF){
//				Maxdis[a][b] = Mindis[a][b] = l;
//				dis[a][b] = 1;
//			}
		}
		
		if(Flag){
			puts("false");
			continue;
		}
		
		for(int i = 1; i <= n + 1; i++){
			SPFA1(i);
			SPFA2(i);
//			printf("i = %d\n", i);
//			for(int j = 1; j <= n + 1; j++){
//				printf("%d : Max = %lld Min = %lld\n", j, Maxdis[i][j], Mindis[i][j]);
//			}
			for(int j = i + 1; j <= n + 1; j++){
				if(Mindis[i][j] < INF){
					if(Maxdis[i][j] != Mindis[i][j]){
						Flag = true;
						break;
					}
				}
			}
			if(Flag) break;
		}
		if(Flag){
			puts("false");
		}
		else{
			puts("true");
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/DyingShu/article/details/82805306