Ligthoj 1407 Explosion

来源:互联网 发布:淘宝如何吸引流量 编辑:程序博客网 时间:2024/06/15 06:18

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1407

题目大意:

有一个机器产生m个限制,限制有4种: 

1.  x or y 至少有1个人参加

2. x不参加 则 y必须不参加,(隐含 y参加 x必须参加

3. x or y 至少有1个人不参加

4. x & y 同时参加 或者不参加

有 k 个人 进行投票,有2种类别

1. x y z 至少有一个人参加

2. x y z 至少有一个人不参加


有n 个人参加会议,m 个机器限制,k个人投票 (3 ≤ n ≤ 1000, 0 ≤ m ≤ 2000, 0 ≤ k ≤ 5)

解题思路:肯定是 2-sat,k比较小直接枚举3^k。剩下的就是一个模板。

纪念一下我写的第二个2-sat的题目。

//#pragma comment(linker,"/STACK:102400000,102400000")#include<stdio.h>#include<iostream>#include<string.h>#include<math.h>#include<algorithm>#include<vector>#include<map>#include<set>#include<queue>#include<string>#include<time.h>#include<stdlib.h>#include<ctype.h>#include<list>//#include<ext/rope>#define PB push_back#define MP make_pair#define PF push_front#define lson k<<1#define rson k<<1|1using namespace std;typedef long long ll;typedef double db;typedef long double ldb;const int N = 1005;/// from 0 to n-1struct TwoSat{    int n;    vector<int> link[N << 1];    bool mk[N << 1];    int ch[5][4], stk[N], top; /// the size of stk is N or N*2 ???    int k, a[5];    void setmk()    {        for(int i = 0; i < n << 1; i++) mk[i] = false;    }    void init(int n, int k)    {        this->n = n;        this->k = k;        for(int i = 0; i < n << 1; i++) link[i].clear();        setmk();    }    void add(int op, int x, int y)    {        if(op == 1) link[x << 1 | 1].PB(y << 1), link[y << 1 | 1].PB(x << 1);        else if(op == 2) link[x << 1 | 1].PB(y << 1 | 1), link[y << 1].PB(x << 1);        else if(op == 3) link[x << 1].PB(y << 1 | 1), link[y << 1].PB(x << 1 | 1);        else        {            link[x << 1 | 1].PB(y << 1), link[y << 1 | 1].PB(x << 1);            link[x << 1].PB(y << 1 | 1), link[y << 1].PB(x << 1 | 1);        }    }    bool dfs(int x)    {        if(mk[x ^ 1]) return false;        if(mk[x]) return true;        mk[x] = true;        stk[++top] = x;        for(int i = 0; i < link[x].size(); i++)            if(!dfs(link[x][i])) return false;        return true;    }    bool solve()    {        for(int i = 0; i < n << 1; i += 2)        {            if(!mk[i] && !mk[i + 1])            {                top = 0;                if(!dfs(i))                {                    while(top) mk[stk[top--]] = false;                    if(!dfs(i + 1)) return false;                }            }        }        return true;    }    void input(int j)    {        for(int i = 0; i < 4; i++) scanf("%d", &ch[j][i]);    }    bool work(int p)    {        if(p == k)        {            setmk();            for(int i = 0; i < k; i++)            {                int t = abs(a[i]) << 1;                t -= 2;                if(a[i] < 0) ++t;                top = 0;                if(!dfs(t)) return false;            }            if(solve()) return true;            return false;        }        else        {            for(int i = 1; i < 4; i++)            {                if(ch[p][0] == 1) a[p] = ch[p][i];                else a[p] = -ch[p][i];                if(work(p + 1)) return true;            }            return false;        }    }    void output()    {        int cnt(0);        for(int i = 0; i < n << 1; i += 2) if(mk[i]) cnt++;        printf(" %d", cnt);        for(int i = 0; i < n << 1; i += 2) if(mk[i]) printf(" %d", (i >> 1) + 1);    }} st;int main(){#ifdef PKWV    //    freopen("in.in", "r", stdin);#endif // PKWV    int T, cas(1);    scanf("%d", &T);    while(T--)    {        int n, m, k;        scanf("%d%d%d", &n, &m, &k);        st.init(n, k);        for(int i = 0; i < m; i++)        {            int op, x, y;            scanf("%d%d%d", &op, &x, &y);            x--, y--;            st.add(op, x, y);        }        for(int i = 0; i < k; i++) st.input(i);        printf("Case %d: ", cas++);        if(st.work(0))        {            printf("Possible");            st.output();            printf(".\n");        }        else printf("Impossible.\n");    }    return 0;}


0 0
原创粉丝点击