小K的農場 差分約束

小K的農場

  跑最長路

1 a-b>=c  建立b到a權值爲c的路

2 a-b<=c----->  b-a>=-c  建立a到b權值爲-c的路

3 a=b   建立a到b,b到a的雙向權值爲0的路

問滿足以上所有條件的情況是否存在,則就是問是否存在負環。改寫spfa爲dfs.

indfs[ i ]表示 i 是否正在被dfs, book[ i ]表示 i 點是否訪問過。如果一個點在dfs且再次回到路徑小於上次就存在環。

#include <bits/stdc++.h>
using namespace std;
#define INF 0x7fffffff
struct Edge{
	int v,w,nxt;
};
int cnt,head[100000];
Edge edge[100000];
int book[10005],dis[10005],indfs[100005],n,m;
int read(){
	int x=0,dign=1;
	char c = getchar();
	while(c<'0'||c>'9'){
		if(c=='-')dign=-1;
		c = getchar();
	}
	while(c>='0'&&c<='9'){
		x = x*10 + c - '0';
		c = getchar();
	}
	return x*dign;
}
void add(int u,int v,int w){
	cnt++;
	edge[cnt].v = v; edge[cnt].w = w;
	edge[cnt].nxt = head[u];
	head[u] = cnt;
}
bool spfa(int u){
		indfs[u] = 1;
		for(int w,v,i=head[u];i;i=edge[i].nxt){
			v = edge[i].v; w = dis[u] + edge[i].w;
			if(!book[v]||dis[v]<w){
				if(indfs[v])return false;//一個點通過一段路徑回到這個點比之前更優存在環 
				book[v] = 1;
				dis[v]=w;
				if(!spfa(v))return false;
			}	
		}
		indfs[u] = 0;
		return true; 
}
int main()
{
	n = read(); m = read();
	for(int i=0;i<=n;i++)add(0,i,0);
	
	for(int i=0;i<m;i++){
		int t,a,b,c;
		t = read();
		if(t==3){
			a = read(); b = read();
			add(b,a,0);
			add(a,b,0);
		}else if(t==1){
			a = read(); b = read(); c = read();
			add(b,a,c);
		}else{
			a = read(); b = read(); c = read();
			add(a,b,-c);	
		}
	}
	for(int i=1;i<=n;i++)dis[i] = -1;
	dis[0] = 0; book[0] = 1;

	if(!spfa(0))printf("No\n");
	else printf("Yes\n"); 
	return 0;
 } 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章