UVAlive3211_Now or later

白书上的例题。

每种航班可以选择两种时间降落,如果想任意航班降落时间差的最小值最大,应该如何安排?

二分时间,如果两个时间只差小于当前枚举的时间,说明这条边不可选,可以根据2sat的方法构图。

然后判断安排方案是否合法即可。

召唤代码君:

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 5555
#define maxm 26666666
using namespace std;

int to[maxm],next[maxm],first[maxn],edge;
int t[maxn],Q[maxn],top=0;
int n,m;
bool mark[maxn];

int abs(int x)
{
    return x>=0?x:-x;
}

void addedge(int U,int V)
{
    edge++;
    to[edge]=V,next[edge]=first[U],first[U]=edge;
}

bool dfs(int cur)
{
    if (mark[cur^1]) return false;
    if (mark[cur]) return true;
    Q[++top]=cur,mark[cur]=true;
    for (int i=first[cur]; i!=-1; i=next[i])
        if (!dfs(to[i])) return false;
    return true;

}

bool check(int x)
{
    edge=-1;
    for (int i=2; i<=n+n+1; i++) first[i]=-1,mark[i]=false;
    for (int i=2; i<=n+n+1; i++)
        for (int j=(i|1)+1; j<=n+n+1; j++)
            if (abs(t[i]-t[j])<x) addedge(i,j^1),addedge(j,i^1);
    for (int i=2; i<=n+n; i+=2)
    {
        if (mark[i] || mark[i+1]) continue;
        top=0;
        if (!dfs(i))
        {
            while (top) mark[Q[top--]]=false;
            if (!dfs(i+1)) return false;
        }
    }
    return true;
}

int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        for (int i=1; i<=n; i++) scanf("%d%d",&t[i+i],&t[i+i+1]);
        int l=0,r=10000000,mid;
        while (l<r)
        {
            mid=(l+r+1)>>1;
            if (check(mid)) l=mid;
                else r=mid-1;
        }
        printf("%d
",l);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lochan/p/3858145.html