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         
View Code

 

你可能感兴趣的:(枚举)