又是类似食物链的这一类题
这题是找与根节点的和差关系 因为0节点是已知的 为0 那么所有的都可以转换为与0的和差关系
可以规定合并的两节点 由大的指向小的 然后再更新和差关系
有可能最后有的不在0集合中 这时要确定最大初值 当然根据集合中出现的负值来确定 题目中工资不能出现负值 也不可大于10^9 在处理完关系后 再判断一下这两个条件 不满足的话就输出m
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 using namespace std; 8 #define N 50010 9 #define LL long long 10 #define maxz 1000000000 11 int n,m; 12 int f[N]; 13 LL r[N],mm[N]; 14 int find(int x) 15 { 16 if(x!=f[x]) 17 { 18 int o = f[x]; 19 f[x] = find(f[x]); 20 r[x] += r[o]; 21 } 22 return f[x]; 23 } 24 int main() 25 { 26 int i,a,b,c; 27 int flag = 0,tx = maxz; 28 scanf("%d%d",&n,&m); 29 for(i = 0 ; i < n ; i++) 30 { 31 f[i] = i; 32 r[i] = 0; 33 } 34 for(i = 1 ;i <= m ; i++) 35 { 36 scanf("%d%d%d",&a,&b,&c); 37 if(flag) 38 continue; 39 int x = find(a),y = find(b); 40 if(x!=y) 41 { 42 if(x<y) 43 { 44 swap(x,y); 45 swap(a,b); 46 c = -c; 47 } 48 f[x] = y; 49 r[x] = -r[a]+r[b]+c; 50 } 51 else 52 { 53 if(r[a]-r[b]!=c) 54 { 55 flag = 1; 56 tx = i; 57 58 } 59 } 60 } 61 for(i = 1; i < n ; i++) 62 { 63 int ho = find(i); 64 if(ho!=0) 65 { 66 if(r[i]<0) 67 { 68 mm[ho] = max(mm[ho],-r[i]); 69 } 70 } 71 } 72 for(i = 1 ; i < n ; i++) 73 { 74 int ff = find(i); 75 if((r[i]+mm[ff])>maxz||(r[i]+mm[ff])<0) 76 { 77 flag = 1; 78 tx = m; 79 break; 80 } 81 } 82 if(flag) 83 { 84 printf("Impossible after %d statements ",tx); 85 return 0; 86 } 87 puts("Possible"); 88 printf("0 "); 89 for(i = 1; i < n ; i++) 90 { 91 int ff = find(i); 92 printf("%lld ",r[i]+mm[ff]); 93 } 94 return 0; 95 }