HDU 4496 D-CITY(并查集)
2014-01-14 22:53
381 查看
HDU 4496 D-CITY(并查集)
题意:
给出一个有N(0<N<=10000)个顶点的无向图(顶点编号0到N-1), 然后依次给出它的M(0<M<=100000)条边,要求依次输出当删除给出的前k(1<=K<=M)条边后,该图的连通分量总数。
输入:第一行是N和M,然后是M行数(X,Y)(0<=X,Y<N)表示X与Y有边。
输出:依次输出所求的连通分量数。
分析:
当删除前K条边时图所剩的连通分量数
就是 N个点孤立时只添加后M-K条边时,所具有的连通分量数。
所以仅需倒序插入每条边,分别保存插入边后新图所具有的连通分量数目在数组内,然后输出数组即可。
进阶1:如果题目要求每次输出删除前i条边后的连通分量数目且i是随机给的呢?
只需要将所有i按从大到小排序,然后离线处理所有的i询问之后按序输出所有结果就行。
进阶2:如果题目要求在线处理每条请求呢?即要求及时给出每个i对应的连通分量数目。
只需要预处理所有可能的i询问结果,然后输出指定询问结果即可。
AC代码(新):
AC代码:中未加while(scanf("%d%d",&n,&m)==2)这行而直接用scanf("%d%d",&n,&m);就得到wrong的结果。
new AC code:
题意:
给出一个有N(0<N<=10000)个顶点的无向图(顶点编号0到N-1), 然后依次给出它的M(0<M<=100000)条边,要求依次输出当删除给出的前k(1<=K<=M)条边后,该图的连通分量总数。
输入:第一行是N和M,然后是M行数(X,Y)(0<=X,Y<N)表示X与Y有边。
输出:依次输出所求的连通分量数。
分析:
当删除前K条边时图所剩的连通分量数
就是 N个点孤立时只添加后M-K条边时,所具有的连通分量数。
所以仅需倒序插入每条边,分别保存插入边后新图所具有的连通分量数目在数组内,然后输出数组即可。
进阶1:如果题目要求每次输出删除前i条边后的连通分量数目且i是随机给的呢?
只需要将所有i按从大到小排序,然后离线处理所有的i询问之后按序输出所有结果就行。
进阶2:如果题目要求在线处理每条请求呢?即要求及时给出每个i对应的连通分量数目。
只需要预处理所有可能的i询问结果,然后输出指定询问结果即可。
AC代码(新):
#include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn=10000+5; const int maxm=100000+5; //并查集fa int fa[maxn]; int findset(int x) { return fa[x]==-1? x : fa[x]=findset(fa[x]); } int bind(int u,int v) { int fu=findset(u); int fv=findset(v); if(fu!=fv) { fa[fu]=fv; return 1;//连通分量少了1个 } return 0; } int main() { int n,m; while(scanf("%d%d",&n,&m)==2) { memset(fa,-1,sizeof(fa)); //vc按序保存所有的边 vector<pair<int,int> > vc; for(int i=0;i<m;i++) { int x,y; scanf("%d%d",&x,&y); vc.push_back(make_pair(x,y)); } //保存连通分量数 vector<int> res; int cnt=n;//当前连通分量数 res.push_back(cnt); for(int i=m-1;i>=1;i--)//逆序依次连接所有边 { cnt -= bind(vc[i].first,vc[i].second); res.push_back(cnt); } for(int i=res.size()-1;i>=0;i--) printf("%d\n",res[i]); } return 0; }
AC代码:中未加while(scanf("%d%d",&n,&m)==2)这行而直接用scanf("%d%d",&n,&m);就得到wrong的结果。
#include<cstdio> using namespace std; int pa[10000+200]; int x[100000+100],y[100000+100],sum[100000+100]; int findset(int x) { return pa[x]==x?x:pa[x]=findset(pa[x]); } int main() { int n,m; while(scanf("%d%d",&n,&m)==2) { for(int i=0; i<m; i++) scanf("%d%d",&x[i],&y[i]); for(int i=0; i<n; i++) pa[i]=i; sum[m-1]=n;//一条边都没有时的连通分量数 for(int i=m-1; i>=0; i--) //一次加上从m-1到0号的边 { int u=findset(x[i]),v=findset(y[i]); if(u!=v) { pa[u]=v; sum[i-1]=sum[i]-1;//sum[i]表删除前i号边(边从0开始计数到m-1)后剩的连通分量数 } else sum[i-1]=sum[i]; } for(int i=0; i<m; i++) printf("%d\n",sum[i]); } return 0; }
new AC code:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=10000+5; const int maxm=100000+5; int n,m; int ans[maxm];//ans[i]==x表删除前i条边所具有的连通分量 struct Edge//边 { int u,v; }edges[maxm]; //并查集 int fa[maxn]; int findset(int x){ return fa[x]==-1?x:fa[x]=findset(fa[x]); } int bind(int u,int v) { int fu=findset(u); int fv=findset(v); if(fu!=fv) { fa[fu]=fv; return 1; } return 0; } int main() { while(scanf("%d%d",&n,&m)==2) { memset(fa,-1,sizeof(fa)); for(int i=1;i<=m;i++) scanf("%d%d",&edges[i].u,&edges[i].v); ans[m]=n; for(int i=m-1;i>=0;i--) { int u=edges[i+1].u, v=edges[i+1].v; ans[i]=ans[i+1]-bind(u,v); } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }
相关文章推荐
- Tiled源码分析: 序
- iOS中Block介绍(一)基础
- HDU4639
- 大端法、小端法、网络字节序
- HDU 1164(质因子的分解)
- Zend Framework 2 : Event and DI
- HDU4545
- 使用Dhcpstarv解决DHCP服务器冲突问题
- 到驾校报名
- 扩展方法
- ActionsTest框架 阅读笔记
- 栈的一个问题。
- 黑马程序员---集合框架<泛型>
- IRC扫盲——你可以不会玩QQ,但不能不会IRC!
- android入门:zxing学习笔记
- HDU4778
- Java开发十大常用网站
- Java开发十大常用网站
- Linux Qt下Qstring转string 中文路径文件乱码
- gocode 安装