bzoj 1202 狡猾的商人
这个题一开始以为是线性规划,但实际上是类似用并查集维护连通信息的题目。
我们先给t+1,这样[s,t]的区间就可以连起来了,那么只要来了一组[s,t]曾经连通过,并且维护的区间值和原来不一样,那么一定是假的。
那么怎么维护区间值呢,我们合并的时候,把t的父亲连到s的父亲上,在t的父亲上存一个t的父亲到s的父亲的区间值也就是:
g[ft]=g[s]+z-g[t];
路径压缩的时候,同时更新g的值,这里注意一个细节:先路径压缩,在用g[f[i]]更新g[i]值,我在这里一直WA。
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 10000 7 #define inf 2147483646 8 using namespace std; 9 int f[maxn],g[maxn]; 10 int n,m,p; 11 12 inline int find(int i) 13 { 14 if (!f[i]) return i; 15 int tmp=find(f[i]);//先更新g[f[i]] 16 g[i]+=g[f[i]]; 17 return f[i]=tmp;//后路径压缩 18 } 19 20 int main() 21 { 22 //freopen("trader.in","r",stdin); 23 scanf("%d",&p); 24 while (p--) 25 { 26 scanf("%d %d",&n,&m); 27 for (int i=0;i<=n+1;i++) f[i]=0,g[i]=0; 28 int x,y,z; 29 bool ans=1; 30 for (int i=1;i<=m;i++) 31 { 32 scanf("%d %d %d",&x,&y,&z); 33 if (!ans) continue; 34 y++; 35 int fx=find(x),fy=find(y); 36 if (fx!=fy) 37 f[fy]=fx,g[fy]=g[x]+z-g[y]; 38 else 39 if (g[y]-g[x]!=z) ans=0; 40 } 41 if (ans) printf("true\n"); 42 else printf("false\n"); 43 } 44 return 0; 45 } 46 47
AC without art, no better than WA !