HDU 4496-D-City(并查集)
D-City
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 6470 Accepted Submission(s): 2213
Problem Description
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.
Input
First line of the input contains two integers N and M.
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.
Output
Output M lines, the ith line is the answer after deleting the first i edges in the input.
Sample Input
5 10
0 1
1 2
1 3
1 4
0 2
2 3
0 4
0 3
3 4
2 4
Sample Output
1
1
1
2
2
2
2
3
4
5
Hint
The graph given in sample input is a complete graph, that each pair of vertex has an edge connecting them, so there’s only 1 connected block at first.
The first 3 lines of output are 1s because after deleting the first 3 edges of the graph, all vertexes still connected together.
But after deleting the first 4 edges of the graph, vertex 1 will be disconnected with other vertex, and it became an independent connected block.
Continue deleting edges the disconnected blocks increased and finally it will became the number of vertex, so the last output should always be N.
问题描述
卢克塞(Luxer)真是个坏人。他摧毁了他遇见的一切。
一天,卢克塞去了D-city。D-city有N个D点和M条D线。每条D线正好连接两个D点。卢克索将销毁所有D线。D-city的市长想知道在Luxer销毁输入中的前K条D-line之后还剩下多少D-city的相连街区。
当且仅当两个点直接或间接相互连接时,它们才在相同的连接块中。
输入值
输入的第一行包含两个整数N和M。
随后的M行分别包含2个以空格分隔的整数u和v,表示D行。
范围:
0 <N <= 10000
0 <M <= 100000
0 <= u,v <N.
输出量
输出M行,第i行是删除输入中前i个边后的答案。
样本输入
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
提示:
样本输入中给出的图是一个完整的图,每对顶点都有一条边将它们连接起来,因此一开始只有一个连接的块。
输出的前3行为1,因为删除图形的前3个边后,所有顶点仍连接在一起。
但是在删除图形的前4个边后,顶点1将与其他顶点断开连接,并成为一个独立的连接块。
继续删除边缘,断开连接的块增加,最后它将变为顶点数,因此最后一个输出应始终为N。
题目大意:给出N个城市和要删除的M个边,意思是现在这N个城市通过M条路彼此相连(给的图不一定是连通的),然后输出依次拆除第 i 条有几个连通的区域。
解题思路:这个题考查并查集,和以往不同的是这个我们可以倒着存,一开始都是互相不连通的,然后从最后一条路往上连通,因为要输出m次,所以我们设置一个ans数组,让ans一开始等n,因为我们要倒着连,所以一开始一定是互相不连通的,然后连一次判断一次,如果父亲节点不同则能连通,ans–,如果父亲节点相同则继续连,最后依次输出ans的值即可。AC代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int _max=1e5+50;
struct node {int a,b;};
int f[_max],s[_max];
node ai[_max];
int main()
{
int n,m;
int getf(int);
while(~scanf("%d%d",&n,&m))
{
int a,b,cnt=1;;
for(int i=1;i<=m;i++)
scanf("%d%d",&ai[i].a,&ai[i].b);
for(int i=0;i<n;i++)
f[i]=i;//初始化并查集
int sum=n;
for(int i=m;i>0;i--)
{
s[i]=sum;
int x=getf(ai[i].a);
int y=getf(ai[i].b);
if(x!=y)//判断父亲节点是否相同
{
sum--;
f[y]=x;
}
}
for(int i=1;i<=m;i++)
printf("%d\n",s[i]);
}
//system("pause");
return 0;
}
int getf(int v)//寻找父亲节点
{
if(f[v]==v)
return v;
else
{
f[v]=getf(f[v]);
return f[v];
}
}