这个题可以用并查集做,这里是之前一个图论学傻了的蒟蒻的差分约束做法。。
我们考虑题面中的条件,
若s到t的为w,就相当于sum[t]-sum[s-1]=w。
那么就是sum[t]-sum[s-1]>=w,sum[t]-sum[s-1]<=w,
同时化成最短路松弛形式得到:sumt[s-1]+w<=sum[t],sum[t]+(-w)<=sum[s-1]。
那么容易发现,只需要从s-1向t连一条w的边,再从t向s-1连一条-w的边就好了。
最后就是直接spfa判环就好了。
#include <bits/stdc++.h> using namespace std; inline int gi () { int x=0,w=0;char ch=0; while(!(ch>='0'&&ch<='9')) { if(ch=='-') w=1; ch=getchar(); } while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return w?-x:x; } const int N=110; const int M=2010; bool inq[N]; queue <int> q; int w,n,m,s,end,Sum,tot,flag,cnt[N],vis[N],head[N],val[N]; struct edge { int next, now, ver; }e[M]; void make (int from, int to, int v) { e[++tot].next=head[from]; head[from]=tot; e[tot].now=to; e[tot].ver=v; } bool SPFA (int k) { memset (val,-0x3f3f3f3f,sizeof (val)); memset (cnt,0,sizeof (cnt)); memset (inq,0,sizeof (inq)); q.push (k); inq[k]=1, val[k]=0; int x,y,i; while (!q.empty ()) { x=q.front (); q.pop (), inq[x]=0, vis[x]=1; for (i=head[x];i;i=e[i].next) { y=e[i].now; if (val[x]+e[i].ver>val[y]) { if (++cnt[y]>=n) return 0; val[y]=val[x]+e[i].ver; if (!inq[y]) q.push (y), inq[y]=1; } } } return 1; } int main () { w=gi (); while (w--) { n=gi (), m=gi (); tot=0; flag=0; memset (head,0,sizeof (head)); memset (vis,0,sizeof (vis)); memset (&e,0,sizeof (e)); for (int i=1;i<=m;++i) { s=gi (), end=gi (), Sum=gi (); make (s-1, end, Sum), make (end, s-1, -Sum); } for (int i=0;i<=n;++i) { if (vis[i]) continue; if (!SPFA (i)) { flag=1; break; } } flag?printf ("false "):printf ("true "); } return 0; }
带权并查集还是比这个快了不少,贴波代码
#include <string> #include <cstdio> #include <cstring> #define IL inline #define RG register #define LL long long using namespace std; IL int gi () { RG int x=0,w=0; char ch=0; while (ch<'0'||ch>'9') {if (ch=='-') w=1; ch=getchar();} while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return w?-x:x; } const int N=110; int fa[N],dis[N]; int get_fa (int x) { if (x==fa[x]) return x; RG int fx=fa[x]; fa[x]=get_fa (fa[x]); dis[x]+=dis[fx]; return fa[x]; } int main () { RG int T,n,m,s,t,v,i,flag; T=gi (); while (T--) { n=gi(),m=gi(),flag=0; memset (fa,0,sizeof(fa)); memset (dis,0,sizeof(dis)); for (i=1;i<=n;++i) fa[i]=i; while (m--) { s=gi()-1,t=gi(),v=gi(); RG int fas=get_fa(s),fat=get_fa(t); if (fas==fat) { if (dis[t]!=dis[s]+v) flag=1; } else fa[fat]=fas,dis[fat]=dis[s]-dis[t]+v; } puts(flag?"false":"true"); } return 0; }