1. 程式人生 > >HDOJ 4496 D-City(並查集變形,逆序 刪邊)

HDOJ 4496 D-City(並查集變形,逆序 刪邊)



D-City

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2656    Accepted Submission(s): 928


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.
題意:市長要在魔王破壞道路後修復道路,以確保每個地區暢通。給出n個城市,m條道路。魔王破壞的道路按序給 出,規定直接連通或者間接連通的區域為同一片地區。問在魔王破壞到k條路時,城市被分成了幾個區域。依次輸出。 題解: 這是一個並查集刪邊問題,在連線好的圖中按照題意刪去邊徑,判斷剩下的聯通區個數。處理時用逆序建圖 的方法,從魔王最後破壞的路開始合併地區。 具體程式碼如下:
#include<cstdio>
#include<cstring>
#define max 100010
int set[10010],count;
int ans[max],x[max],y[max];

int find(int x)
{
	int r=x;
	int t;
	while(r!=set[r])
		r=set[r];
	while(r!=x)
	{
		t=set[x];
		set[x]=r;
		x=t;
	}
	return r;
}

void merge(int a,int b,int k)
{
	int fa=find(a);
	int fb=find(b);
	if(fa!=fb)
	{
		count--;//連通之前沒有連通地區後 
		set[fa]=fb;
	}
	ans[k]=count;
}

int main()
{
	int n,m,i;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(i=0;i<n;++i)
		    set[i]=i;
		for(i=0;i<m;++i)
			scanf("%d%d",&x[i],&y[i]);
		ans[m]=n;
		count=n;
		for(i=m-1;i>0;i--)
		   merge(x[i],y[i],i);
		for(i=1;i<=m;++i)
		   printf("%d\n",ans[i]);
	}
	return 0;
}