Luxer is a really bad guy. He destroys everything he met.
One day Luxer went to D-city. D-city has N D-points and M D-lines. Each D-line connects exactly two D-points. Luxer will destroy all the D-lines. The mayor of D-city wants to know how many connected blocks of D-city left after Luxer destroying the first K D-lines in the input.
Two points are in the same connected blocks if and only if they connect to each other directly or indirectly.
One day Luxer went to D-city. D-city has N D-points and M D-lines. Each D-line connects exactly two D-points. Luxer will destroy all the D-lines. The mayor of D-city wants to know how many connected blocks of D-city left after Luxer destroying the first K D-lines in the input.
Two points are in the same connected blocks if and only if they connect to each other directly or indirectly.
Then following M lines each containing 2 space-separated integers u and v, which denotes an D-line.
Constraints:
0 < N <= 10000
0 < M <= 100000
0 <= u, v < N.
5 10 0 1 1 2 1 3 1 4 0 2 2 3 0 4 0 3 3 4 2 4
1 1 1 2 2 2 2 3 4 5算法:
//正常并查集是一条一条边的加,然后判断联通块,但这个刚好反过来,
//那么直接储存反过来记录查询就行了
#include <cstdio>
#include <algorithm>
#define INF 0x3f3f3f3f
#define max1 100000+50
#define max2 10000+50
int par[max2],a[max1];
using namespace std;
struct Node{
int a,b;
}data[max1];
int find(int x)
{
if(x!=par[x])
return par[x]=find(par[x]);
return x;
}
void join(int a, int b)
{
int fa = find(a);
int fb = find(b);
if (fa != fb)
par[fa] = fb;
}
int main()
{
int m,n;
int ans;
while(scanf("%d %d",&n,&m)!=EOF)
{
ans=n;//最初n个城市,连通块个数为n
for(int i = 0; i < m; i++)
scanf("%d %d",&data[i].a,&data[i].b);
for(int i = 0; i < n; i++)
par[i]=i;
for(int i=m-1; i>=0;i--)//倒序查询合并
{
a[i]=ans;
if(find(data[i].a)!=find(data[i].b))
{
ans--;//如果不连通就把他们连起来,个数减一
}
join(data[i].a,data[i].b);
}
for (int i=0;i<m;i++)
{
printf("%d\n",a[i]);
}
}
return 0;
}