题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4496
这个题目没什么好说的,赤裸裸的并查集
题目说的是依次去除前面k个,那么只要先离线接受数据,然后从后面往前建立并查集就OK了
最后一个结果肯定是n,后来只要并的两个集合不是同一个集合那么就结果减1,否则结果不变!
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define maxn 150000
#define MIN(a,b) (a<b?a:b)
struct point{
int a,b;
}po[maxn];
int n,m,rec[maxn],ans[maxn];
int init(){
for(int i=0;i<=n;i++)
rec[i]=i;
return 0;
}
int find_root(int a){
int b=a,c;
while(rec[a]!=a)
a=rec[a];
while(b!=a){
c=rec[b];
rec[b]=a;
b=c;
}
return a;
}
bool union_set(int a,int b){
a=find_root(a),b=find_root(b);
rec[a]=MIN(a,b);
rec[b]=MIN(a,b);
return a!=b;
}
int main(){
int i,j,k,now;
while(scanf("%d%d",&n,&m)!=EOF){
init();
for(i=0;i<m;i++)
scanf("%d%d",&po[i].a,&po[i].b);
now=n;
i=m;m--;
for( ;m>=0;m--){
ans[m]=now;
if(union_set(po[m].a,po[m].b)) now--;
}
m=i;
for(i=0;i<m;i++)
printf("%d\n",ans[i]);
}
return 0;
}