codeforces 1027f F. Session in BSU

链接: http://codeforces.com/contest/1027/problem/F

题意:小明有n场考试,每场考试可以在a或者b天考,但是小明每天只能做一套考试卷子,问你小明能否考完所有的考试如果可以输出最大的考试日,如果不可以,输出-1

思路: 看问题其实是一个最优匹配的问题,如果我们我们把点分为两类,左边的点为考试,右边的点为某天。那么我们要做的就是找到左边点全部匹配并且右边的点最小的点。 注意到这里的每一场考试只有两个考试日,也就是只有两个天数点与他相连,那么我可以把这个考试点缩掉,缩成边,那么就可以转化为为每个边匹配一个与他相邻的点,使得最大的点最小。

这里图就分成了几个联通块,那么对于每个联通块,如果他的节点数等于边数,那么肯定都要选。如果节点数等于边数+1,那么我只需要加次小的节点。 如果边数> 点数,肯定是无解呀。

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int ,int > pii;
const int N =2e6+5;

int f[N];
int num[N];
pii a[N];
int tot;
int vis[N];
int vise[N];
int totn,totm;
int mx,ci;
int n;
vector<pii> ve[N];

void init()
{
    tot=0;
    for(int i=0;i<N;i++) f[i]=i;
}

int getf(int x)
{
    return f[x]==x?x:(f[x]=getf(f[x]));
}

void merge(int x,int y)
{
    int t1=getf(x);
    int t2=getf(y);
    if(t1>t2) swap(t1,t2);
    if(t1!=t2){
        f[t2]=t1;
    }
}

void dfs(int u)
{
    if(vis[u]) return ;
    vis[u]=1;
    if(u>mx){
        ci=mx;
        mx=u;
    }
    else if(u>ci){
        ci=u;
    }

    totn++;
    for(int i=0;i<ve[u].size();i++){
        int v=ve[u][i].first;
        int id=ve[u][i].second;
        if(vise[id]==0){
            vise[id]=1;
            totm++;
        }
        if(!vis[v]){
            dfs(v);
        }
    }
}

int main()
{
    init();
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d %d",&a[i].first, &a[i].second);
        num[++tot]=a[i].first; num[++tot]=a[i].second;
    }
    sort(num+1,num+tot+1);
    tot=unique(num+1,num+tot+1)-(num+1);
    for(int i=1;i<=n;i++){
        a[i].first=lower_bound(num+1,num+tot+1,a[i].first)-num;
        a[i].second=lower_bound(num+1,num+tot+1,a[i].second)-num;
    }

    for(int i=1;i<=n;i++){
        merge(a[i].first,a[i].second);
        ve[a[i].first].push_back(pii(a[i].second,i));
        ve[a[i].second].push_back(pii(a[i].first,i));
    }

    ///for(int i=1;i<=n;i++) cout<<a[i].first<<" *** "<<a[i].second<<endl;

    int Ans=0;
    for(int i=1;i<=tot;i++){
        int fa=getf(i);
        if(i==fa){
            //cout<<"fa "<<fa<<endl;
            totn=0; totm=0;
            mx=0;
            ci=0;
            dfs(i);
            if(totn<totm){
                cout<<-1<<endl;
                return 0;
            }
            if(totn==totm){
                Ans=max(Ans,mx);
            }
            else if(totm+1==totn){
                Ans=max(Ans,ci);
            }
        }
    }

    cout<<num[Ans]<<endl;
    return 0;
}

/*

3
23 27
22 26
27 30

*/

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/82500692
今日推荐