UVALive3713_Astronauts

有n个宇航员,根据年龄限制,所有宇航员只能从事A或B中的一种任务,所有人都可以从事C的任务。有的宇航员之间相互讨厌,不能分在一组,求出一种满足条件的分配方案。

2sat。mark[]中i+i和i+i+1分别表示i从事C工作或者他的特有工作。

对于仇恨关系,我们可以知道U和V两个人不能同时从事C工作。于是加边 (U+U,V+V+1),(V+V,U+U+1)。

同时,如果这两个人的特有工作相同,那么还需要加边(U+U+1,V+V),(V+V+1,U+U)。

召唤代码君:

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 5555550
using namespace std;

int age[maxn],n,m;
int next[maxn],to[maxn],first[maxn],edge;
bool mark[maxn];//0 C  1 A|B
int Q[maxn],top;
double avg;

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;
}

int main()
{
    int U,V;
    while (scanf("%d%d",&n,&m) && (n|m))
    {
        avg=0,edge=-1;
        for (int i=1; i<=n; i++)
        {
            scanf("%d",&age[i]);
            avg+=age[i];
            mark[i+i]=mark[i+i+1]=false;
            first[i+i]=first[i+i+1]=-1;
        }
        avg/=n;
        while (m--)
        {
            scanf("%d%d",&U,&V);
            addedge(U+U,V+V+1),addedge(V+V,U+U+1);
            if ((age[U]<avg)^(age[V]<avg)) continue;
            addedge(U+U+1,V+V),addedge(V+V+1,U+U);
        }
        bool flag=true;
        for (int i=1; i<=n; i++)
        {
            if (mark[i+i] || mark[i+i+1]) continue;
            top=0;
            if (!dfs(i+i))
            {
                while (top) mark[Q[top--]]=false;
                if (!dfs(i+i+1))
                {
                    flag=false;
                    break;
                }
            }
        }
        if (flag)
        {
            for (int i=1; i<=n; i++)
                if (mark[i+i]) printf("C
");
                    else printf("%c
",age[i]>=avg?'A':'B');
        }
        else puts("No solution.");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lochan/p/3858358.html