洛谷AT3882
题目链接https://www.luogu.org/problem/AT3882
WA了好多,但是依旧不知为何而错
我的错误代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> using namespace std; const int maxn = 1e7+5; int pre[maxn],dis[maxn]; ////错误 int find(int x){ while(x!=pre[x]){ int r = pre[x]; pre[x] = pre[r]; dis[x] += dis[r]; x = r; } return x; } bool merge(int x,int y,int d){ int px = find(x); int py = find(y); if(px==py){ return d==(dis[y]-dis[x]); } pre[py] = px ; dis[py] = dis[x]+d-dis[y]; return true; } void init(){ for(int i=0;i<maxn;i++){ pre[i] = i; } } int main() { init(); int n,m,ans=1; cin>>n>>m; for(int i=0;i<m;i++){ int x,y,d; cin>>x>>y>>d; if(ans){ ans = merge(x,y,d); } } if(ans){ cout<<"Yes"<<endl; }else{ cout<<"No"<<endl; } return 0; }
错误原因:超时,我的路径压缩仅仅压缩了一层,而答案的路径压缩,压缩至根节点
AC代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> using namespace std; const int maxn = 1e7+5; int pre[maxn],dis[maxn]; int find(int x){ if(x==pre[x]){ return x; } int r = find(pre[x]); dis[x] += dis[pre[x]]; return pre[x] = r; } bool merge(int x,int y,int d){ int px = find(x); int py = find(y); if(px==py){ return d==(dis[y]-dis[x]); } pre[py] = px ; dis[py] = dis[x]+d-dis[y]; return true; } void init(){ for(int i=0;i<maxn;i++){ pre[i] = i; } } int main() { init(); int n,m,ans=1; cin>>n>>m; for(int i=0;i<m;i++){ int x,y,d; cin>>x>>y>>d; if(ans){ ans = merge(x,y,d); } } if(ans){ cout<<"Yes"<<endl; }else{ cout<<"No"<<endl; } return 0; }
并查集路径压缩:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int find(int x) { if(x == par[x]) return x; else return par[x] = find(par[x]); } //路径压缩(与返回父亲节点) void unite(int x, int y) { x = find(x); y = find(y); if(x == y) return ; if(Rank[x] <= Rank[y]) par[x] = y; else par[y] = x; if(Rank[x] == Rank[y]) Rank[x]++; } //秩优化 与 合并操作