loj 1407(2-sat + 枚举 + 输出一组可行解 )

来源:互联网 发布:声学模拟软件 编辑:程序博客网 时间:2024/05/18 22:40

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27115

思路:有一个trick要注意:当情况为 2 x y 时,可以推出当y留下时,x也必须留下。然后就是后面的k个限制关系,我们可以3^(k)次方枚举,一旦找到符合条件的就return 。然后就是反向建图,拓扑排序找可行解。

  1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<algorithm>  5 #include<stack>  6 #include<queue>  7 #include<vector>  8 #include<cmath>  9 using namespace std; 10 #define MAXN 2222 11  12 int n,m,k; 13 struct Node{ 14     int tag; 15     int num[3]; 16 }node[7]; 17  18 vector<vector<int> >g,gg,edge; 19  20 int cnt,bcc_count; 21 int dfn[MAXN],low[MAXN],color[MAXN]; 22 int degree[MAXN]; 23 bool mark[MAXN]; 24 stack<int>S; 25  26 void Tarjan(int u) 27 { 28     low[u]=dfn[u]=++cnt; 29     mark[u]=true; 30     S.push(u); 31     for(int i=0;i<edge[u].size();i++){ 32         int v=edge[u][i]; 33         if(dfn[v]==0){ 34             Tarjan(v); 35             low[u]=min(low[u],low[v]); 36         }else if(mark[v]){ 37             low[u]=min(low[u],dfn[v]); 38         } 39     } 40     if(low[u]==dfn[u]){ 41         int v; 42         bcc_count++; 43         do{ 44             v=S.top(); 45             S.pop(); 46             mark[v]=false; 47             color[v]=bcc_count; 48         }while(u!=v); 49     } 50 } 51  52 int opp[MAXN]; 53 bool Check() 54 { 55     for(int i=1;i<=n;i++){ 56         if(color[i]==color[i+n])return false; 57         opp[color[i]]=color[i+n]; 58         opp[color[i+n]]=color[i]; 59     } 60     return true; 61 } 62  63 bool Judge() 64 { 65     int kk=(int)pow(3.0,k); 66     for(int i=0;i<kk;i++){ 67         for(int j=1;j<=2*n;j++)edge[j]=g[j]; 68         int j=i,_count=0; 69         while(_count<k){ 70             int id=j%3; 71             int x=node[_count].num[id]; 72             if(node[_count].tag==1){ 73                 edge[x+n].push_back(x); 74             }else  75                 edge[x].push_back(x+n); 76             _count++; 77             j/=3; 78         } 79         cnt=bcc_count=0; 80         memset(dfn,0,sizeof(dfn)); 81         memset(mark,false,sizeof(mark)); 82         for(int j=1;j<=2*n;j++)if(dfn[j]==0)Tarjan(j); 83         if(Check())return true; 84     } 85     return false; 86 } 87  88 int vis[MAXN]; 89 void TopSort() 90 { 91     queue<int>que; 92     for(int i=1;i<=bcc_count;i++){ 93         if(degree[i]==0)que.push(i); 94     } 95     memset(vis,0,sizeof(vis)); 96     while(!que.empty()){ 97         int u=que.front(); 98         que.pop(); 99         if(vis[u]==0){100             vis[u]=1;101             vis[opp[u]]=-1;102         }103         for(int i=0;i<gg[u].size();i++){104             int v=gg[u][i];105             if(--degree[v]==0)que.push(v);106         }107     }108 }109 110 vector<int>ans;111 void Solve()112 {113     gg.clear();114     gg.resize(2*n+2);115     memset(degree,0,sizeof(degree));116     for(int u=1;u<=2*n;u++){117         for(int i=0;i<edge[u].size();i++){118             int v=edge[u][i];119             if(color[u]!=color[v]){120                 gg[color[v]].push_back(color[u]);121                 degree[color[u]]++;122             }123         }124     }125     TopSort();126     ans.clear();127     for(int i=1;i<=n;i++)128         if(vis[color[i]]==1)ans.push_back(i);129     printf("%d",(int)ans.size());130     for(int i=0;i<(int)ans.size();i++){131         printf(" %d",ans[i]);132     }133     puts(".");134 }135 136 int main()137 {138     int _case,x,y,z,tag,t=1;139     scanf("%d",&_case);140     while(_case--){141         scanf("%d%d%d",&n,&m,&k);142         g.clear();143         g.resize(2*n+2);144         edge.clear();145         edge.resize(2*n+2);146         while(m--){147             scanf("%d%d%d",&tag,&x,&y);148             if(tag==1)g[x+n].push_back(y),g[y+n].push_back(x);149             else if(tag==2)g[x+n].push_back(y+n),g[y].push_back(x);150             else if(tag==3)g[x].push_back(y+n),g[y].push_back(x+n);151             else g[x].push_back(y+n),g[y].push_back(x+n),g[x+n].push_back(y),g[y+n].push_back(x);152         }153         for(int i=0;i<k;i++){154             scanf("%d%d%d%d",&node[i].tag,&node[i].num[0],&node[i].num[1],&node[i].num[2]);155         }156         printf("Case %d: ",t++);157         if(Judge()){158             printf("Possible ");159             Solve();160         }else 161             puts("Impossible.");162     }163     return 0;164 }165         
View Code

 

0 0
原创粉丝点击