lightoj 1407 2-sat

这题的英语either...or....很蛋疼;

m中,1:x与y至少一个出席;2:x出席,y随便,x不出席,y也不出席----这有个坑,可以推出y出席x也一定出席(这个关系必须要连上);3x与y至少一个不出席   4,x与y有且只有一个出席。  

对于k中的数据:我琢磨很久,关系在图上是建不了的,type为1时三个人至少有一个人要出席,则三个都不出席的情况是不允许的,dfs的时候判断一下就是了,同理type为2的情况。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 1310;
const int maxe = 100000;
const int INF = 0x3f3f3f;

int n,m,k;
struct node{
    int type,x,y,z;
}a[6];

struct TwoSat{
    int n;
    int mark[maxn*2];
    int s[maxn*2],cnt;
    vector<int> G[maxn*2];

    void init(int n){
        this->n = n;
        for(int i=2;i<=2*n+1;i++)  G[i].clear();
        memset(mark,0,sizeof(mark));
    }
    void add_clause1or3(int u,int uval,int v,int vval){
        u = u*2 + uval;      //u与v不共存;
        v = v*2 + vval;
        G[u].push_back(v^1);
        G[v].push_back(u^1);
    }
    void add_clause2(int u,int uval,int v,int vval){
        u = u*2 + uval;
        v = v*2 + vval;
        G[u].push_back(v);
        G[v^1].push_back(u^1);
    }
    void add_clause4(int u,int uval,int v,int vval){
        u = u*2 + uval;
        v = v*2 + vval;
        G[u^1].push_back(v);
        G[u].push_back(v^1);
        G[v^1].push_back(u);
        G[v].push_back(u^1);
    }

    bool JudgeWrong(){
        for(int i=0;i<k;i++){
            if(a[i].type == 1){
                int x = 2*a[i].x+1,y = 2*a[i].y+1,z = 2*a[i].z+1;
                if(mark[x] && mark[y] && mark[z]) return true;
            }
            if(a[i].type == 2){
                int x = 2*a[i].x,y = 2*a[i].y,z = 2*a[i].z;
                if(mark[x] && mark[y] && mark[z]) return true;
            }
        }
        return false;
    }

    bool dfs(int u){
        if(mark[u^1])   return false;
        if(mark[u])     return true;
        mark[u] = true;
        s[cnt++] = u;
        if(JudgeWrong())     return false;

        for(int i=0;i<G[u].size();i++)
            if(!dfs(G[u][i]))  return false;
        return true;
    }

    bool solve(){
        for(int i=2;i<=2*n;i+=2)
            if(!mark[i] && !mark[i+1]){
                cnt = 0;
                if(!dfs(i)){
                    while(cnt > 0)    mark[s[--cnt]] = false;       //要回溯;
                    if(!dfs(i+1))  return false;
                }
            }

        return true;
    }

    void print(){
        int ans[maxn],pv = 0;
        for(int i=2;i<=2*n;i+=2)
            if(mark[i])  ans[pv++] = i/2;

        printf("%d",pv);
        for(int i=0;i<pv;i++)  printf(" %d",ans[i]);
        printf(".\n");
    }

}solver;

int main()
{
    //freopen("E:\\acm\\input.txt","r",stdin);
    int T;
    cin>>T;
    for(int t=1;t<=T;t++){
        scanf("%d %d %d",&n,&m,&k);
        solver.init(n);
        for(int i=1;i<=m;i++){
            int type,x,y;
            scanf("%d %d %d",&type,&x,&y);
            if(type == 1)         solver.add_clause1or3(x,1,y,1);
            else if(type == 2)    solver.add_clause2(x,1,y,1);
            else if(type == 3)    solver.add_clause1or3(x,0,y,0);
            else                  solver.add_clause4(x,0,y,0);
        }
        for(int i=0;i<k;i++)
            scanf("%d %d %d %d",&a[i].type,&a[i].x,&a[i].y,&a[i].z);
        if(solver.solve()){
            printf("Case %d: Possible ",t);
            solver.print();
        }
        else   printf("Case %d: Impossible.\n",t);
    }
}
View Code

 

 

posted @ 2013-08-17 17:04  等待最好的两个人  阅读(216)  评论(0编辑  收藏  举报