Codeforces_1027F_Session in BSU(并查集维护二分图)

版权声明: 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;
}

猜你喜欢

转载自blog.csdn.net/yyy_3y/article/details/81908776
今日推荐