lightoj 1251 (Two_Sat)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

const int maxn = 20050;
const int INF  = 0x3f3f3f;

int n,m;
char a[maxn][2];
int b[maxn][2];

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

    void init(int n){
        this->n = n;
        memset(mark,0,sizeof(mark));
        for(int i=0;i<=2*n;i++)  G[i].clear();
    }

    void add_clause(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);
    }

    bool dfs(int u){
        if(mark[u^1])    return false;
        if(mark[u])      return true;
        mark[u] = true;
        s[cnt++] = u;  //记录你所选择的路径;
        for(int i=0;i<G[u].size();i++ ){
           if( !dfs(G[u][i]) )    return false;
        }
        return true;
    }

    bool solve(){
        for(int i=0;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=0;i<2*n;i+=2){
            if(mark[i] && a[i/2][0] == '+'){
                ans[pv++] = b[i/2][0];
            }
            else  if(mark[i+1] && a[i/2][1] == '+'){
                ans[pv++] = b[i/2][1];
            }
        }
        sort(ans,ans+pv);
        int num = unique(ans,ans+pv)  - ans;
        printf("%d",num);
        for(int i=0;i<num;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",&n,&m);
        solver.init(n);
        vector<int> p1[8008],p2[8008],n1[8008],n2[8008];
        for(int i=0;i<n;i++){
            int temp;
            scanf("%c%c%d%c%c%d",&temp,&a[i][0],&b[i][0],&temp,&a[i][1],&b[i][1]);
            if(a[i][0] == '+'){
                p1[b[i][0]].push_back(i);
                p2[b[i][0]].push_back(0);
            }
            else{
                n1[b[i][0]].push_back(i);
                n2[b[i][0]].push_back(0);
            }
            if(a[i][1] == '+'){
                p1[b[i][1]].push_back(i);
                p2[b[i][1]].push_back(1);
            }
            else{
                n1[b[i][1]].push_back(i);
                n2[b[i][1]].push_back(1);
            }
        }
        for(int i=1;i<=m;i++){
            for(int j=0;j<p1[i].size();j++)
               for(int k=0;k<n1[i].size();k++){
                  solver.add_clause(p1[i][j],p2[i][j],n1[i][k],n2[i][k]);
            }
        }
        if(solver.solve()){
            printf("Case %d: Yes\n",t);
            solver.print();
        }
        else       printf("Case %d: No\n",t);
    }
}
View Code

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

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