hdu 3047 Zjnu Stadium 带权并查集
Zjnu Stadium
题意:题中讲列数总共为300,但是行数不限。即广场每一圈的半径无限大,但是阶梯层数为300;并且每一次输入A(1<=A<=N), B(1<=B<=N), X(0<=X<300)就表示A,B在同一行(列数没用。。不用mod),并且认为B在A的右边X处;N,M分别表示输入的数值不会超过N,叙述不会超过M;还是问里面有几句话与之前的话矛盾;
思路:带权并查集,只需在压缩路径时将dist[]同时增加即可;dist[a] += dist[f[a]];
注后面加的不是dist[fa]虽然前面fa = Find(f[a]);但是是在return 时才f[a] = fa;我们加的是没压缩之前的dist[f[a]],即从后往前递推处理到要累加的u,v的dist;
265MS 1960K #include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) const int MAXN = 50050; int f[MAXN],dist[MAXN]; int Find(int a)//** { if(a == f[a]) return f[a]; int fa = Find(f[a]); dist[a] += dist[f[a]];//加上没压缩之前的fa,此时dist[f[a]]已经递推到了要fa的距离 return f[a] = fa; } bool solve(int u,int v,int w) { int fu = Find(u),fv = Find(v); if(fu == fv && dist[v] != dist[u] + w) return true; f[fv] = fu; dist[fv] = dist[u] + w - dist[v]; // 压缩时计算到根节点的距离,现在计算两个根节点距离; return false; } int main() { int N,M; while(scanf("%d%d",&N,&M) == 2){ rep1(i,0,N) dist[i] = 0,f[i] = i; int A,B,X,ans = 0; rep0(i,0,M){ scanf("%d%d%d",&A,&B,&X); if(solve(A,B,X)) ans++; } printf("%d\n",ans); } return 0; }