博文:https://blog.csdn.net/yjr3426619/article/details/82315133
带全并查集
路径压缩,表达每个当前node与 当前node所在的并查集的root 之间的关系
并查集一定是单向连通的,所以一些node处理时 【node1,node2】 weight 可能需要把 一端的闭区间变为开区间
俩个相对信息求出绝对信息 --水题
例题 : HDU 3038
//带权值并查集 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 2e5 + 25; int dis[maxn]; int p[maxn]; int find(int u)//寻根 { if(u!=p[u]) { int tmp = p[u];//保存原来的根节点 p[u] = find(p[u]);//路径压缩 dis[u] += dis[tmp];//dis[tmp] 已经为tmp(即原来父节点)到根节点的距离所以加上本身自身到tmp的dis则为u到root的dis } return p[u]; } void merge(int u,int v,int value) { int f1 = find(u); int f2 = find(v); p[f1] = f2; dis[f1] = value + dis[v] - dis[u]; }//带权并查集合并 int main() { int n,m;//n节点,m条边 while(cin>>n>>m) { int ans = 0,u,v,value; for(int i=0;i<=n;++i) { dis[i] = 0; p[i] = i; } while(m--) {//图改成了从0开始(important) cin>>u>>v>>value; --u; if(find(u)==find(v)) { if((dis[u]-dis[v])!=value) ++ans; }else{ merge(u,v,value);//否则合并 } } cout<<ans<<endl; } }
hihoCoder 1515
//带权并查集 #include<iostream> #include<cstdio>//不是同一集合,合并,否则不做操作 #include<algorithm> #include<cstring> using namespace std; const int maxn = 1e5 + 15; int dis[maxn],p[maxn];//当前node到root的距离 int find(int u) { if(u!=p[u]) { int tmp = p[u]; p[u] = find(p[u]); dis[u] += dis[tmp]; } return p[u]; } int main() { int n,m,q;//n个节点,m条边,q个查询 while(cin>>n>>m>>q) { for(int v=1;v<=n;++v) { dis[v] = 0; p[v] = v; } int u,v,value; while(m--) { cin>>u>>v>>value; int f1 = find(u); int f2 = find(v); if(f1!=f2) { p[f1] = f2; dis[f1] = value + dis[v] - dis[u]; } } while(q--) { cin>>u>>v; if(find(u)!=find(v)) cout<<-1<<endl; else cout<<dis[u] - dis[v]<<endl; } } }
原文地址:https://www.cnblogs.com/newstartCY/p/11601164.html
时间: 2024-11-08 11:45:57