UVALive-3713 Astronauts (2-SAT)

题目大意:有三个任务A、B、C,n个已知年龄的人。A任务只能被年龄不小于平均年龄的人做,B任务只能被平均年龄以下的人做,C任务不限,相互讨厌的两个人不能做同一件任务,现在已知厌恶关系,求一种任务分配方案。

题目分析:每个人都有两个选择,对于年龄大的人,设选A为真,选C为假,对年龄小的人,设选B为真,选C为假。相互讨厌的两个人X、Y若同类,X、Y只能一真一假,也就是X、Y不能同真也不能同假,连边:X1->Y0、Y1->X0、X0->Y1、Y0->X1;若X、Y不是同类,则X、Y不能同时为假,连边:X0->Y1、Y0->X1。

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;

const int maxn=100005;
vector<int>G[2*maxn];
int mark[2*maxn],Age[maxn],S[maxn],cnt;
double x;

bool same(int a,int b)
{
    if(Age[a]>=x&&Age[b]>=x)
        return true;
    if(Age[a]<x&&Age[b]<x)
        return true;
    return false;
}

bool dfs(int u)
{
    if(mark[u^1])   return false;
    if(mark[u]) return true;
    mark[u]=1;
    S[cnt++]=u;
    for(int i=0;i<G[u].size();++i)
        if(!dfs(G[u][i]))
            return false;
    return true;
}

bool judge(int n)
{
    memset(mark,0,sizeof(mark));
    for(int i=0;i<2*n;i+=2){
        cnt=0;
        if(!dfs(i)){
            while(cnt>0)  mark[S[--cnt]]=0;
            if(!dfs(i+1))   return false;
        }
    }
    return true;
}

int main()
{
    int n,m,a,b;
    while(scanf("%d%d",&n,&m)&&(n+m))
    {
        for(int i=0;i<2*n;++i)  G[i].clear();
        x=0.0;
        for(int i=0;i<n;++i){
            scanf("%d",Age+i);
            x+=Age[i];
        }
        x/=n;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            --a,--b;
            G[2*a+1].push_back(2*b);
            G[2*b+1].push_back(2*a);
            if(same(a,b)){
                G[2*a].push_back(2*b+1);
                G[2*b].push_back(2*a+1);
            }
        }
        if(!judge(n))
            printf("No solution.
");
        else    for(int i=0;i<2*n;i+=2){
            if(!mark[i])
                printf("C
");
            else
                printf("%c
",(Age[i/2]>=x)?'A':'B');
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/4902823.html