[洛谷]P1330 封鎖陽光大學 (#並查集 )

題目描述

曹是一隻愛刷街的老曹,暑假期間,他每天都歡快地在陽光大學的校園裏刷街。河蟹看到歡快的曹,感到不爽。河蟹決定封鎖陽光大學,不讓曹刷街。

陽光大學的校園是一張由N個點構成的無向圖,N個點之間由M條道路連接。每隻河蟹可以對一個點進行封鎖,當某個點被封鎖後,與這個點相連的道路就被封鎖了,曹就無法在與這些道路上刷街了。非常悲劇的一點是,河蟹是一種不和諧的生物,當兩隻河蟹封鎖了相鄰的兩個點時,他們會發生衝突。

詢問:最少需要多少隻河蟹,可以封鎖所有道路並且不發生衝突。

輸入格式

第一行:兩個整數N,M

接下來M行:每行兩個整數A,B,表示點A到點B之間有道路相連。

輸出格式

僅一行:如果河蟹無法封鎖所有道路,則輸出“Impossible”,否則輸出一個整數,表示最少需要多少隻河蟹。

輸入輸出樣例

輸入 #1複製

3 3
1 2
1 3
2 3

輸出 #1複製

Impossible

輸入 #2複製

3 2
1 2
2 3

輸出 #2複製

1

說明/提示

【數據規模】

1<=N<=10000,1<=M<=100000,任意兩點之間最多有一條道路。


思路

有一個由n個結點構成的有m條邊的圖,需要在某幾個點上放置河蟹,河蟹會佔領該點上的所有邊,相鄰的河蟹之間會發生衝突,目的要讓河蟹佔領整個圖。

我用的並查集,具體做法是把一張圖分層,有點類似於bfs。一個合理的圖不會出現同一層之間互相連接的邊。這種圖叫做分層圖。

如果分層後,同一層兩點之間有邊相連,就可以判定不行。

河蟹直接不能相鄰,那麼我們只要讓河蟹佔據奇數層或者偶數層的所有點,不就ok?那麼我們可以用並查集維護每一層。並查集的作用是使某些點具有相同的祖宗結點,那麼他們直接就屬於一個集合。同理,讓奇數層的點屬於同一個集合,偶數點屬於同一集合,有點類似於關押罪犯。

#include <stdio.h>
#include <iostream>
#include <memory.h>
using namespace std;
int n,m,s1,s2,fa[100001]/*每個節點的祖宗是誰*/,e[100001][2]/*記錄圖信息*/
bool vis[100001];
int getfind(int v)//認爹函數 
{
	if(fa[v]==v)//祖宗節點是自己 
	{
		return v;
	}
	else//繼續認爹 
	{
		fa[v]=getfind(fa[v]);
		return fa[v];
	}
}
inline void merge(int v,int u)//合併 
{
	register int t1,t2;
	t1=getfind(v);//找他們的祖宗節點 
	t2=getfind(u);
	if(t1!=t2)//不相同,就合併集合 
	{
		fa[t2]=t1;
	}
	return;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j;
	cin>>n>>m;
	for(i=1;i<=n*2;i++)
	{
		fa[i]=i;
	}
	for(i=1;i<=m;i++)
	{
		cin>>e[i][0]>>e[i][1];
		int t1(getfind(e[i][0])),t2(getfind(e[i][1]));//先找祖先 
		if(t1==t2)//祖先一樣,且他們在同一層 
		{
			cout<<"Impossible"<<endl;
			return 0;
		}
		else
		{
			merge(e[i][0]+n,e[i][1]);
			merge(e[i][0],e[i][1]+n);
		}
	}
	memset(vis,1,sizeof(vis));//以i爲根節點的圖是否放置和諧 
	int s(0);
	for(i=1;i<=m;i++)
	{
		int t1(getfind(e[i][0])),t2(getfind(e[i][1]));
		if(vis[t1]==1 && vis[t2]==1)//如果沒有 
		{
			vis[t1]=0;
			vis[t2]=0;
			s1=s2=0;
			for(j=1;j<=n;j++)//在改分層圖進行遍歷找最佳答案 
			{
				if(getfind(j)==t1) s1++;
				else if(getfind(j)==t2) s2++;
			}
			s+=min(s1,s2);
		}
	}
	cout<<s<<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章