codeforces 1027F Session in BSU

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/zzk_233/article/details/83274947

首先我们把日期看成点,每个考试都连接了两个点,而合法的情况就是每条边都至少有一个点和他配对,和二分图匹配很像。。

但是时间明显不够,那么我们可以转换思路,通过连边,原图变为了一些连通块,而对于每个连通块,就有以下几种情况

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;
}

猜你喜欢

转载自blog.csdn.net/zzk_233/article/details/83274947