Codeforces 292D [Connected Components]--并查集的巧妙应用
2017-07-11 09:26
423 查看
【链接】
Codeforces 292D
【题目大意】
给你N个节点和M条边以及Q次询问。对于每一次询问给你两个数li,ri表示不取区间li~ri的边,并输出连通块的个数。
【解题报告】
因为li~ri里的边是不取的,求的又是连通块的个数,所以考虑要取的边。首先想到的是一个O(N*M*Q)的暴力直接搞,但是时间复杂度扛不住。这是就想到了预处理记l[i]表示1~i的边构成的图中每个节点的父亲是谁,r[i]表示i~n的边构成的图中每个节点的父亲是谁,预处理的时间复杂度为O(N*M)。所以对于每次询问就可以O(N)回答,时间复杂度O(N*Q)。
Codeforces 292D
【题目大意】
给你N个节点和M条边以及Q次询问。对于每一次询问给你两个数li,ri表示不取区间li~ri的边,并输出连通块的个数。
【解题报告】
因为li~ri里的边是不取的,求的又是连通块的个数,所以考虑要取的边。首先想到的是一个O(N*M*Q)的暴力直接搞,但是时间复杂度扛不住。这是就想到了预处理记l[i]表示1~i的边构成的图中每个节点的父亲是谁,r[i]表示i~n的边构成的图中每个节点的父亲是谁,预处理的时间复杂度为O(N*M)。所以对于每次询问就可以O(N)回答,时间复杂度O(N*Q)。
#include<cstdio> using namespace std; const int maxn=505,maxm=10005; int n,m,Q; struct wjd { int x,y; }a[maxm]; struct UF { int fa[maxn]; void Clear(){for (int i=1; i<=n; i++) fa[i]=i;} int Getfa(int x){if (fa[x]==x) return x; fa[x]=Getfa(fa[x]); return fa[x];} void Merge(int x,int y) {x=Getfa(x); y=Getfa(y); if (x!=y) fa[x]=y;} }L[maxm],R[maxm],Fa;//并查集 inline int Read() { int res=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=getchar(); return res; } int Query(int l,int r) { for (int i=1; i<=n; i++) Fa.fa[i]=L[l].fa[i]; for (int i=1; i<=n; i++) Fa.Merge(i,R[r].Getfa(R[r].fa[i])); int sum=0; for (int i=1; i<=n; i++) if (i==Fa.Getfa(i)) sum++; return sum; } int main() {#include<cstdio> using namespace std; const int maxn=505,maxm=10005; int n,m,Q; struct wjd { int x,y; }a[maxm]; struct UF { int fa[maxn]; void Clear(){for (int i=1; i<=n; i++) fa[i]=i;} int Getfa(int x){if (fa[x]==x) return x; fa[x]=Getfa(fa[x]); return fa[x];} void Merge(int x,int y) {x=Getfa(x); y=Getfa(y); if (x!=y) fa[x]=y;} }L[maxm],R[maxm],Fa; inline int Read() { int res=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=getchar(); return res; } int Query(int l,int r) { for (int i=1; i<=n; i++) Fa.fa[i]=L[l].fa[i]; for (int i=1; i<=n; i++) Fa.Merge(i,R[r].Getfa(R[r].fa[i])); int sum=0; for (int i=1; i<=n; i++) if (i==Fa.Getfa(i)) sum++; return sum; } int main() { freopen("292D.in","r",stdin); freopen("292D.out","w",stdout); n=Read(); m=Read(); for (int i=1; i<=m; i++) a[i]=(wjd){Read(),Read()}; L[0].Clear(); R[m+1].Clear(); for (int i=1; i<=m; i++) L[i]=L[i-1],L[i].Merge(a[i].x,a[i].y); for (int i=m; i; i--) R[i]=R[i+1],R[i].Merge(a[i].x,a[i].y); Q=Read(); for (int i=1; i<=Q; i++) { int l=Read(),r=Read(); printf("%d\n",Query(l-1,r+1)); } return 0; } n=Read(); m=Read(); for (int i=1; i<=m; i++) a[i]=(wjd){Read(),Read()}; L[0].Clear(); R[m+1].Clear(); for (int i=1; i<=m; i++) L[i]=L[i-1],L[i].Merge(a[i].x,a[i].y);//构造L数组 for (int i=m; i; i--) R[i]=R[i+1],R[i].Merge(a[i].x,a[i].y);//构造R数组 Q=Read(); for (int i=1; i<=Q; i++) { int l=Read(),r=Read(); printf("%d\n",Query(l-1,r+1)); } return 0; }
相关文章推荐
- Codeforces 432C (哥德巴赫猜想的巧妙应用)
- 并查集巧妙用法(codeforces)C. Destroying Array
- CodeForces 295B - Greg and Graph Floyd的巧妙应用
- CodeForces 292D Connected Components(并查集 前后缀)
- Codeforces 292D (并查集巧妙运用)
- Codeforces 292D Connected Components (并查集)
- 并查集及其应用
- 并查集(Union-Find Sets)及其应用
- 并查集及其应用
- 并查集及其应用——kruscal法求最小生成树
- 邮件实用技巧五:巧妙应用你的个性签名
- css中z-index与position属性的巧妙应用
- PKU2513 - Colored Sticks --一道很不错的题(结合了并查集的应用,字典树的应用,欧拉通路的原理)
- Linux tail命令的巧妙应用
- LCA算法--并查集应用
- POJ 1988 并查集的应用 很好地体现了并查集的一些特点
- Pku acm 1611 The Suspects数据结构题目解题报告(九)---- 并查集的应用
- 并查集 (Union-Find Sets)及其应用
- 巧妙利用union用来判断大小端的应用
- 并查集 (Union-Find Sets)及其应用