1. 程式人生 > >codeforces 1027F Session in BSU

codeforces 1027F Session in BSU

首先我們把日期看成點,每個考試都連線了兩個點,而合法的情況就是每條邊都至少有一個點和他配對,和二分圖匹配很像。。

但是時間明顯不夠,那麼我們可以轉換思路,通過連邊,原圖變為了一些連通塊,而對於每個連通塊,就有以下幾種情況

1.這個連通塊是個樹,那麼每條邊都有點,還多出一個點,所以最後要找的就是次大的點。

2.這個連通塊是一個基環樹(就是隻有一個環的樹),那麼每個點正好對應一條邊,要用的就是最大的點。

3.這個連通塊的邊數>點數,那麼一定不合法,輸出-1即可。

PS:對於2和3情況的判定我換了好幾種方法終於對了。。。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
using namespace std;
map<int,int>M,N;
int cnt,n,used[2000006],hh[2000006];
vector<int>W[2000006];
int maxx,flag,cimax,ans;
struct dd
{
	int u,v;
}ddd[1000006];
void dfs(int u,int fa)
{
	used[u]++;
	if(u<maxx)cimax=max(cimax,u);
	else if(u>maxx) cimax=maxx,maxx=u;
	int l=W[u].size()-1;
	for(int i=0;i<=l;i++)
	{
		if(W[u][i]==fa)continue;
		if(used[W[u][i]])
		{
			used[W[u][i]]++;
			if(used[W[u][i]]==2)
			{
				flag++;
				if(flag>2)//有多組環不合法
				{
					printf("-1");
					exit(0);
				}
			}
			if(used[W[u][i]]>2)//一個點被超過2條邊連不合法
			{
				printf("-1");
				exit(0);
			}
			continue;
		}
		dfs(W[u][i],u);
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&ddd[i].u,&ddd[i].v);
		hh[++cnt]=ddd[i].u,hh[++cnt]=ddd[i].v;
	}
	sort(hh+1,hh+1+cnt);int tr=0;
	for(int i=1;i<=cnt;i++)
	{
		if(!M[hh[i]])M[hh[i]]=++tr,N[tr]=hh[i];
		
	}
	for(int i=1;i<=n;i++)
	{
		W[M[ddd[i].u]].push_back(M[ddd[i].v]);
		W[M[ddd[i].v]].push_back(M[ddd[i].u]);
	}
	for(int i=1;i<=tr;i++)
	{
		maxx=0,cimax=0,flag=0;
		if(!used[i])
		{
			dfs(i,i);
			if(flag)
			{
				ans=max(ans,maxx);
			}else
			{
				ans=max(ans,cimax);
			}
		}	
	}
	printf("%d",N[ans]);
	return 0;
}