HDU1814 Peaceful Commission(2-SAT输出字典序最小的解)

题目链接
HDU1814 Peaceful Commission(2-SAT输出字典序最小的解)_第1张图片

题意

现在有n个党派,每个党派拥有两个候选代表,第i个党派的候选代表为2i-1和2i,两个党派候选人只会有一个去参加会议,此外还有m对候选人互相看不顺眼,只能去其中一个,求字典序最小的代表人选。

思路

一个比较明显的2-SAT问题,但是需要输出最小解,所以似乎不可以用传统的拓扑排序寻找可行解,于是采取了DFS解法,复杂度O(nm),其能选取出最小解的原因应该是采取了顺序的遍历方式。

代码

#include
using namespace std;
const int maxn=1e5+5;
bool mark[maxn];
int k,m,n,cnt,s[maxn],head[maxn];
struct node
{
    int to,next;
}a[maxn];
void add(int u,int v)
{
    a[++k].next=head[u];
    a[k].to=v;
    head[u]=k;
}
void init()
{
    k=0;
    memset(head,0,sizeof head);
}
bool dfs(int x)
{
    if(mark[x^1])
        return false;
    if(mark[x])
        return 1;
    s[++cnt]=x;
    mark[x]=1;
    for(int i=head[x];i;i=a[i].next)
    {
        int to=a[i].to;
        if(!dfs(to))
            return false;
    }
    return true;
}
bool twosat()
{
    memset(mark,0,sizeof mark);
    for(int i=0;i<2*n;i+=2)
    {
        if(!mark[i]&&!mark[i^1])
        {
            cnt=0;
            if(!dfs(i))
            {
                while(cnt)
                    mark[s[cnt--]]=false;
                if(!dfs(i^1))
                    return false;
            }
        }
    }
    return true;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    while(cin>>n>>m)
    {
        init();
        for(int i=1;i<=m;i++)
        {
            int u,v;
            cin>>u>>v;
            u--;v--;
            add(u,v^1);
            add(v,u^1);
        }
        if(twosat())
        {
            for(int i=0;i<2*n;i+=2)
            {
                if(mark[i])
                    cout<<i+1<<endl;
                else
                    cout<<i+2<<endl;
            }
        }
        else
            cout<<"NIE"<<endl;
    }
    return 0;
}

你可能感兴趣的:(图论)