【算法练习】HDU - 1814 Peaceful Commission (2-SAT)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengwill97/article/details/82083324

题意

一国有n个党派。每一个党派在议会中都有2个代表,现要组建和平委员会,要从每一个党派在议会的代表中选出1人,一共n人组成和平委员会。已知有一些代表之间存在仇恨,也就是说他们不能同一时候被选为和平委员会的成员,现要你推断满足要求的和平委员会是否能创立?假设能,请给出字典序最小的方案。

题解

输出字典序最小的,按照白书上的套路来就行了。
这题无限wa,原因是因为在寻找解的时候,每次找要先把保存节点的栈清空掉,否则会WA。

代码

#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int head[nmax], tot;
struct edge {
    int to, nxt;
} e[nmax<<1];
int dfn[nmax], low[nmax], ss[nmax], color[nmax], scc , st, dfs_clock, ban[nmax];
bool instack[nmax], isok;
stack<int> s;
void add_edge(int u, int v) {
    e[tot].to = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}
void init() {
    memset(head, -1, sizeof head);
    memset(dfn ,0, sizeof dfn);
    memset(low, 0, sizeof low);
    memset(color, 0, sizeof color);
    memset(ban, 0, sizeof ban);
    scc = dfs_clock = st = tot = 0;
}
void tarjan(int u) {
    dfn[u] = low[u] = ++dfs_clock;
    ss[st++] = u;
    instack[u] = true;
    for(int i = head[u]; i != -1; i = e[i].nxt) {
        int v = e[i].to;
        if(!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if(instack[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]) {
        scc ++;
        int tmp;
        for(;;) {
            tmp = ss[--st];
            instack[tmp] = false;
            color[tmp] = scc;
            if(tmp == u)
                break;
        }
    }
}
bool dfs(int u) {
    if(ban[u] == 2) return false;
    if(ban[u] == 1) return true;
    if(ban[u ^ 1] == 1) return false;
    if(ban[u ^ 1] == 1) return true;
    ban[u] = 1;
    ban[u ^ 1] = 2;
    s.push(u);
    for(int i = head[u] ; i != -1; i = e[i].nxt) {
        int v = e[i].to;
        if(dfs(v) == false)
            return false;
    }
    return true;
}
int n, m;
int main() {
    while(scanf("%d %d" , &n, &m) != EOF) {
        init();
        for(int i = 1; i <= m; ++i) {
            int u, v;
            scanf("%d %d", &u, &v);
            u--;
            v--;
            add_edge(u, v ^ 1);
            add_edge(v, u ^ 1);
        }
        for(int i = 0; i < 2 * n; ++i) {
            if(!dfn[i])
                tarjan(i);
        }
        bool isok = true;
        for(int i = 0; i < 2 * n; i += 2) {
            if(color[i] == color[i ^ 1]) {
                isok = false;
                break;
            }
        }
        if(!isok) {
            printf("NIE\n");
            continue;
        } else {
            isok = true;
            for(int i = 0; i < 2 * n; i += 2) {
                if(!ban[i] && !ban[i ^ 1]) {
                    while(!s.empty()) s.pop();
                    if(dfs(i) == false) {
                        while(!s.empty()) {
                            int now = s.top();
                            s.pop();
                            ban[now] = ban[now ^ 1] = 0;
                        }
                        dfs(i ^ 1);
                    }
                }
            }
            for(int i = 0; i < 2 * n; i += 2) {
                if(ban[i] == 1)
                    printf("%d\n",i + 1);
                else
                    printf("%d\n",(i^1) + 1);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pengwill97/article/details/82083324