bzoj 1202[HNOI2005]狡猾的商人 (luogu 2294)
阿新 • • 發佈:2018-12-11
演算法:差分約束+並查集(維護)/Floyed
難度:NOIP
題解:
差分約束應該也不難發現,但是這個差分怎麼去維護呢?
這就用到了帶權並查集
差分不等式為f[y]-s[x-1]=z;
維護呢,就去看x,y;是否已經在同一個集合中,如果已經在了,就去判斷是否滿足差分不等式,如果不滿足,就是false;
如果不在同一個集合中,就merge,回溯時更新f即可。
程式碼如下:
#include <cstdio> #include <iostream> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <deque> #include <queue> #define ll long long #define N 20005 using namespace std; int fa[N],f[N]; int findf(int x) { if(x==fa[x]) return x; int temp=fa[x]; fa[x]=findf(fa[x]); f[x]+=f[temp]; return fa[x]; } int main() { int T; scanf("%d",&T); while(T--) { int n,m,fla=0; scanf("%d%d",&n,&m); memset(fa,0,sizeof(fa)); memset(f,0,sizeof(f)); for(int i = 1;i <= n;i++) { fa[i]=i; } for(int i = 1;i <= m;i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); int t1=findf(x-1); int t2=findf(y); if(t1!=t2) { fa[t1]=t2; f[t1]=f[y]-f[x-1]+w; }else if(abs(f[y]-f[x-1])!=abs(w)) { fla=1; } } if(fla) { puts("false"); }else { puts("true"); } } return 0 ; }