1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #define MAXN 10001 5 using namespace std; 6 int uset[MAXN]; 7 int Find(int x){return uset[x]==x?x:uset[x]=Find(uset[x]);} 8 int makeSet(int x,int y){ 9 int fx=Find(x),fy=Find(y); 10 if(fx!=fy){ 11 uset[fy]=fx; 12 return 1; 13 } 14 return 0; 15 } 16 int main() 17 { 18 int x,y,num,line; 19 while(scanf("%d%d",&num,&line)==2){ 20 for(int i=0;i<num;i++) uset[i]=i;// 21 22 int cnt=num; 23 vector<pair<int,int> > v; 24 while(line--){ 25 scanf("%d%d",&x,&y); 26 v.push_back(make_pair(x,y)); 27 } 28 29 vector<int> res;//store the result 30 res.push_back(cnt); 31 for(int i=v.size()-1;i>=1;i--) 32 cnt-=makeSet(v[i].first,v[i].second),res.push_back(cnt); 33 for(int i=res.size()-1;i>=0;i--) 34 printf("%d ",res[i]); 35 } 36 return 0; 37 }
题意:
给出一个有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条边时,所具有的连通分量数。
所以仅需倒序插入每条边,分别保存插入边后新图所具有的连通分量数目在数组内,然后输出数组即可。
(以上摘自http://blog.csdn.net/u013480600/article/details/18278857)
cin和scanf混用是大坑,并且并不知道需要scanf("%d%d",&num,&line)==2来作为结束条件,题目没有说明啊(?)
撇开这些,
- 20行,修改初始化,因为题目节点是从0开始的。
- 12,14,32行,直接计算结果避免再次遍历数组计算连通节点数
- 22,30行,根据题意,破坏最后一个道路,必定是num个连通节点
- 31行,循环到i=1终止,是因为一开始就破坏第一条道路,所以不连接也没事。
- 33行,根据题意倒序输出
需要学习一下pair的用法