题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038
题目大意:
给你n给整数,m次操作。
每次操作是给出三个整数a,b,c; 子序列a~b的和为c。
找出m次操作中有多少次不合法,不合法的操作舍去。
解题思路:
先开一个dis[n]数组,dis[x]记录的是与父节点的距离。
d[x]记录的是[0,x]的和
dis[x]=d[x]-d[pre[x]];
对于每个操作:
1.如果操作合法,则进行更新。
注意:节点小的作为父节点放前面。
2. 如果不合法(前提是父节点相同),即dis[b]-dis[a]不等于c,次数加1.
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <map> 5 #include <algorithm> 6 using namespace std; 7 8 const int maxn=200005; 9 int pre[maxn]; 10 int dis[maxn]; 11 12 int find(int x) 13 { 14 int r=x; 15 if(pre[x]!=x) 16 { 17 r=pre[x]; 18 pre[x]=find(pre[x]); 19 dis[x]+=dis[r]; 20 } 21 return pre[x]; 22 } 23 24 int main() 25 { 26 int n, m, fa, fb, u, v, c, disa, disb; 27 while(cin >> n >> m) 28 { 29 for(int i=0; i<=n; i++) 30 pre[i]=i; 31 memset(dis,0,sizeof(dis)); 32 int ans=0; 33 for(int i=0; i<m; i++) 34 { 35 scanf("%d%d%d",&u,&v,&c); 36 u--; 37 fa=find(u); 38 fb=find(v); 39 if(fa!=fb) 40 { 41 if(fa<fb) 42 { 43 dis[fb]=dis[u]-dis[v]+c; 44 pre[fb]=fa; 45 } 46 else 47 { 48 dis[fa]=dis[v]-dis[u]-c; 49 pre[fa]=fb; 50 } 51 } 52 else 53 { 54 disa=dis[u]; 55 disb=dis[v]; 56 if(disb-disa!=c) 57 ans++; 58 } 59 } 60 cout << ans <<endl; 61 } 62 return 0; 63 }