题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3038/
参考博客:
这是一道带权并查集的题目,设置了根节点到子节点之间的距离,可以利用向量性质更新每段上的值,假定结点编号为a的结点的值S[a]在结点之后的连线上,所以查询[l,r]的时候实际上是看[l,r+1]段,如果定义结点之前的连线上是该结点的值,则查询的区间实际上是[l-1,r]。利用向量性质实际上更新fx->fy=fx->x + x->y - fy->y ,对于一个节点i,S[i]就表示根节点到这个点的区间和。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define mp(a,b) make_pair((a),(b)) 17 #define P pair<int,int> 18 #define dbg(args) cout<<#args<<":"<<args<<endl; 19 #define inf 0x3f3f3f3f 20 const int maxn=1e6+10; 21 int n,m,t; 22 inline int read(){ 23 int ans=0,w=1; 24 char ch=getchar(); 25 while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} 26 while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); 27 return ans*w; 28 } 29 int ans; 30 int f[maxn],s[maxn]; 31 void init() 32 { 33 f(i,1,n) 34 { 35 f[i]=i; 36 s[i]=0; 37 } 38 ans=0; 39 } 40 int find(int x) 41 { 42 if(x==f[x])return x;//到达根结点的时候不需要有任何操作,只需要返回根就行 43 int tmp=f[x];//暂存f当前的根,因为在路径压缩之后当前的根节点会发生变化 44 f[x]=find(f[x]); 45 s[x]+=s[tmp];//将根节点的值加到当前结点上,相当于前缀和 46 return f[x]; 47 } 48 void Union(int x,int y,int num) 49 { 50 int fx=find(x); 51 int fy=find(y); 52 if(fx==fy) 53 { 54 if(s[y]-s[x]!=num)ans++;//x->y=rooty->y - rootx->x 55 } 56 else 57 { 58 f[fy]=fx;//保持根节点的值比较小 59 //fx根节点指向了新的结点,所以他的值需要改变,而原来以fx为根的结点的f值还未变化,所以s值不变 60 s[fy]=s[x]+num-s[y];//s[t]代表的是root->t的和 61 //故有rootx->rooty=rootx->x+x->y-rooty->y=s[x]+num-s[y] 62 } 63 } 64 int main() 65 { 66 //freopen("input.txt","r",stdin); 67 //freopen("output.txt","w",stdout); 68 std::ios::sync_with_stdio(false); 69 while(scanf("%d%d",&n,&m)!=EOF) 70 { 71 init(); 72 int u,v,w; 73 f(i,1,m) 74 { 75 u=read(),v=read(),w=read(); 76 Union(u-1,v,w);//如果f是从0开始的话Union(u,v+1,w)也可用 77 } 78 // f(i,1,n)cout<<i<<":"<<f[i]<<":"<<s[i]<<endl; 79 pf("%d ",ans); 80 } 81 }