uva 11324 the largest clique (2-sat 二分答案)

n架飞机,有早、晚着陆两种方式选择。让你安排着陆方式使得相邻两个着陆时间间隔的最小值尽量大。求该最大值。


建图:

每架飞机i的两个着陆时间视为两个点Ai、Ai+1

设最后答案是T,那么当对于两架飞机,若Ai-Aj <T,说明该两个着陆时间不能同时选择,选择了Ai就得选Aj+1。因此,Ai->Aj+1连一条边

二分答案,再按照上面方式建图求解即可。时间复杂度为O(n^2logT)


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;
#define maxn 4005
#define maxm 32000005

struct Edge{
    int to,next;
}edge[maxm];

int cnt,head[maxn],S[maxn],top;
bool vis[maxn];

inline void add(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}

bool dfs(int u)
{
    if(vis[u^1]) return 0;
    if(vis[u]) return 1;
    vis[u]=1;
    S[top++]=u;
    for(int i=head[u];~i;i=edge[i].next)
        if(!dfs(edge[i].to)) return 0;
    return 1;
}

bool solve(int n)
{
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i+=2)
    {
        if(vis[i]||vis[i^1]) continue;
        top=0;
        if(!dfs(i))
        {
            while(top) vis[S[--top]]=0;
            if(!dfs(i^1)) return 0;
        }
    }
    return 1;
}

int n,T[maxn][2];
bool test(int Time)
{
    cnt=0;
    memset(head,-1,sizeof(head));
    for(int i=0;i<n;++i)
        for(int a=0;a<2;++a)
            for(int j=i+1;j<n;++j)
                for(int b=0;b<2;++b)
                    if(abs(T[i][a]-T[j][b])<Time){
                        add(i*2+a,(2*j+b)^1);
                        add(j*2+b,(2*i+a)^1);
                    }
    return solve(n+n);
}

int main()
{
    while(~scanf("%d",&n)&&n)
    {
        int L=0,R=0;
        for(int i=0;i<n;++i)
            for(int j=0;j<2;++j) {scanf("%d",&T[i][j]);R=max(R,T[i][j]);}
        while(L<R)
        {
            int M=L+(R-L+1)/2;
            if(test(M)) L=M;
            else R=M-1;
        }
        printf("%d\n",L);
    }
    return 0;
}


你可能感兴趣的:(uva 11324 the largest clique (2-sat 二分答案))