[HNOI2005]狡猾的商人
题目
题解
差分约束,貌似也能用并查集???
偷看到的信息是等式关系,用两个不等式表示
x - y >= v
x - y <= v
问是否有解,即判断图中是否存在负环,从每个点开始跑spfa,注意每组数据一定要清空数组和标记!!!
//话说把其余点用较大于-inf的边连起来可以只跑一遍spfa,但好像每个点跑一遍还快些,也许是边多了之后找到负环要多跑很多路
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 10050
#define inf 1000000000
using namespace std;
int T,n,m;
int a[N],b[N],w[N],nt[N],p[N],num;
void add(int x,int y,int v)
{
a[++num]=x;b[num]=y;w[num]=v;
nt[num]=p[x];p[x]=num;
}
int q[10*N],flag[N],dis[N],cnt[N];
bool f;
void spfa(int s)
{
for(int i=0;i<=n;i++) dis[i]=-inf;
dis[s]=0;flag[s]=1;q[1]=s;cnt[s]++;
int head=0,tail=1;
while(head<tail)
{
int k=q[++head];
for(int e=p[k];e;e=nt[e])
{
int kk=b[e];
if(dis[kk]<dis[k]+w[e])
{
dis[kk]=dis[k]+w[e];
if(!flag[kk])
{
flag[kk]=1;
cnt[kk]++;
if(cnt[kk]>=n) {f=1;break;}
q[++tail]=kk;
}
}
}
flag[k]=0;
if(f) break;
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(cnt,0,sizeof(cnt));
memset(nt,0,sizeof(nt));
memset(p,0,sizeof(p));
scanf("%d%d",&n,&m);num=0;f=0;
for(int i=1;i<=m;i++)
{
int x,y,v;scanf("%d%d%d",&x,&y,&v);
add(x-1,y,v);add(y,x-1,-v);
}
for(int i=0;i<=n;i++)
{
if(!cnt[i]) spfa(i);
if(f) break;
}
if(f) printf("false\n");
else printf("true\n");
}
return 0;
}