How Many Answers Are Wrong
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038
题目大意:
在一个长度为n的区间上,给出m个区间和,当遇到给出的这个区间与前面的区间有矛盾时,认为新给出的区间是错误的,不更新区间,问有多少错误区间。区间中的数是任意的。
解题思路:
首先我们定义一个数组$sum$,$sum[i]$存的是第i个数与他的祖宗这段区间的区间和,不包括祖宗点(祖宗点一定小于儿子点)。然后要搞清楚什么情况下可以判断出有冲突,先确定给出的$a(a=a-1),b$两点与他们的祖宗$aa,bb$两点,我们就确定了两个区间,我们要求的是$a$与$b$的距离,也就是两个区间交叉后的后边一段的距离,所以必须要确定出前边几段距离具体的值,所以,可以推出,只有祖宗点位置相同时才能得到$a$到$b$的具体值。接着要处理,当不冲突时更新$sum$数组,与$pre$数组。因为我们规定,祖宗点一定小于儿子点,所以,我们要找到$aa$与$bb$的关系,如$aa<bb$,则$pre[bb]=aa$,算出$sum[bb]$,那么,$a,b,aa,bb$之间的距离都可以表示出来。
代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 #define debug(a) cout<<#a<<":"<<a<<endl;
5 const int INF=0x3f3f3f3f;
6 const int N=1e6+7;
7 const int mod=1e9+7;
8 int maxn,minn;
9 int T,n,m;
10 int pre[N];
11 int sum[N];
12
13 int find(int a){
14 if(pre[a]!=a){
15 int b=pre[a];
16 pre[a]=find(pre[a]);
17 sum[a]=sum[a]+sum[b];
18 }
19 return pre[a];
20 }
21
22 void join(int a,int b,int w){
23 int aa=find(a);
24 int bb=find(b);
25 if(aa<bb){
26 pre[bb]=aa;
27 sum[bb]=sum[a]-(sum[b]-w);
28 }
29 else{
30 pre[aa]=bb;
31 sum[aa]=sum[b]-sum[a]-w;
32 }
33 }
34
35 int main(){
36 int ans;
37 int a,b,w,aa,bb;
38 while(cin>>n>>m){
39 memset(sum,0,sizeof(sum));
40 for(int i=1;i<=n;i++){
41 pre[i]=i;
42 }
43 ans=0;
44 for(int i=1;i<=m;i++){
45 cin>>a>>b>>w;
46 a--;
47 aa=find(a);
48 bb=find(b);
49 if(aa==bb){
50 if(sum[b]-sum[a]!=w){
51 ans++;
52 }
53 }
54 else{
55 join(a,b,w);
56 }
57 }
58 cout<<ans<<endl;
59 }
60 return 0;
61 }