版权声明: https://blog.csdn.net/yyy_3y/article/details/81908776
题意:一个人有n场考试,每场考试有2个可以考试的时间,问是否可以安排上所有的考试,如果可以输出最短的天数。
思路:非常有意思的一道题。现场看到觉得是一个二分图匹配,但是发现数据范围很大(结果还真有二分图过的)。
1)首先需要离散化,这样最多只有2e6的点,可以存的下。
2)我们将点点的模型变成一个点边的模型,将一场考试的两个时间点连一条边,然后如果在一个连通块中如果点数(考试数)=边数,也就是基环树,那么便是这个连通块中最大(晚)的考试日子。如果形成的是一棵树,很显然可以是次大值。其他情况,就表示会产生冲突,直接输出-1即可。
#include<bits/stdc++.h>
#define debug(a) cout << #a << " " << a << endl
#define lnn putchar('\n')
#define see putchar(' ')
#define LL long long
#define ull unsigned long long
#define PI acos(-1.0)
#define eps 1e-6
const int N=2e6+7;
using namespace std;
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int a[N],b[N],c[N*2],ta[N],tb[N];
struct edge
{
int from,to;
};
vector<edge> edges;
vector<int> g[N];
int tot;
void addedge(int u,int v)
{
edges.push_back({u,v});
int m=edges.size()-1;
g[u].push_back(m);
}
int vis[N],dep[N],num,mx,mxx;
void dfs(int x,int pre)
{
vis[x]=1;
if(c[x]>=mx) mxx=mx,mx=c[x];
else mxx=max(mxx,c[x]);
for(int i=0;i<g[x].size();i++){
edge e=edges[g[x][i]];
if(!vis[e.to]){
dep[e.to]=dep[x]+1;
dfs(e.to,x);
}
else{
if(dep[e.to]>dep[x]) num++;
}
}
}
int main ()
{
//yyy_3y
//freopen("1.in","r",stdin);
int n; n=read();
for(int i=1;i<=n;i++){
a[i]=read();b[i]=read();
c[++tot]=a[i];
c[++tot]=b[i];
}
sort(c+1,c+1+tot);
int len=unique(c+1,c+1+tot)-c-1;
for(int i=1;i<=n;i++){
ta[i]=lower_bound(c+1,c+1+len,a[i])-c;
tb[i]=lower_bound(c+1,c+1+len,b[i])-c;
addedge(ta[i],tb[i]);
addedge(tb[i],ta[i]);
}
int ans=0;
for(int i=1;i<=len;i++){
mx=mxx=num=0;
if(!vis[i]){
dfs(i,0);
if(num>=2){
puts("-1");
return 0;
}else if(num==1){
ans=max(ans,mx);
}else if(num==0){
ans=max(ans,mxx);
}
}
}
printf("%d\n",ans);
return 0;
}