loj 1407(2-sat + 枚举 + 输出一组可行解 )
题目链接: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