loj 1251(2-sat + 输出一组可行解)

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

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

思路:u表示留下,~u表示离开,同理v,对于+u,-v,我们可以这样来定义:若u离开,则v必须留下,如v离开,则u必须留下,于是我们可以连边u+n->v,v+n->u,后面的同理。

  1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<algorithm>  5 #include<stack>  6 #include<vector>  7 #include<queue>  8 using namespace std;  9 #define MAXN 20000 10 #define MAXM 444444 11  12 struct Edge{ 13     int v,next; 14 }edge[MAXM]; 15  16 int n,m,NE; 17 int head[MAXN]; 18  19 void Insert(int u,int v) 20 { 21     edge[NE].v=v; 22     edge[NE].next=head[u]; 23     head[u]=NE++; 24 } 25  26 int cnt,bcc_count; 27 int low[MAXN],dfn[MAXN],color[MAXN]; 28 bool mark[MAXN]; 29 stack<int>S; 30  31 void Tarjan(int u) 32 { 33     low[u]=dfn[u]=++cnt; 34     mark[u]=true; 35     S.push(u); 36     for(int i=head[u];i!=-1;i=edge[i].next){ 37         int v=edge[i].v; 38         if(dfn[v]==0){ 39             Tarjan(v); 40             low[u]=min(low[u],low[v]); 41         }else if(mark[v]){ 42             low[u]=min(low[u],dfn[v]); 43         } 44     } 45     if(low[u]==dfn[u]){ 46         int v; 47         bcc_count++; 48         do{ 49             v=S.top(); 50             S.pop(); 51             mark[v]=false; 52             color[v]=bcc_count; 53         }while(u!=v); 54     } 55 } 56  57 int opp[MAXN]; 58 bool Judge() 59 { 60     for(int i=1;i<=n;i++){ 61         if(color[i]==color[i+n])return false; 62         //opp[x]保存的是和编号为x的连通分量矛盾的连通分量的编号 63         opp[color[i]]=color[i+n]; 64         opp[color[i+n]]=color[i]; 65     } 66     return true; 67 } 68  69 vector<vector<int> >g; 70 vector<int>ans; 71 int degree[MAXN]; 72 int vis[MAXN]; 73  74 void TopSort() 75 { 76     queue<int>que; 77     for(int i=1;i<=bcc_count;i++){ 78         if(degree[i]==0)que.push(i); 79     } 80     while(!que.empty()){ 81         int u=que.front(); 82         que.pop(); 83         if(vis[u]==0){ 84             //染色 85             vis[u]=1; 86             vis[opp[u]]=-1; 87         } 88         for(int i=0;i<g[u].size();i++){ 89             degree[g[u][i]]--; 90             if(degree[g[u][i]]==0)que.push(g[u][i]); 91         } 92     } 93 } 94  95  96 int main() 97 { 98     int _case,t=1,a,b,u,v; 99     scanf("%d",&_case);100     while(_case--){101         scanf("%d %d",&m,&n);102         NE=0;103         memset(head,-1,sizeof(head));104         while(m--){105             scanf("%d%d",&a,&b);106             u=abs(a),v=abs(b);107             if(a>0&&b>0)Insert(u+n,v),Insert(v+n,u);108             else if(a>0&&b<0)Insert(u+n,v+n),Insert(v,u);109             else if(a<0&&b>0)Insert(u,v),Insert(v+n,u+n);110             else Insert(u,v+n),Insert(v,u+n);111         }112         cnt=bcc_count=0;113         memset(mark,false,sizeof(mark));114         memset(dfn,0,sizeof(dfn));115         memset(color,0,sizeof(color));116         for(int i=1;i<=2*n;i++)if(dfn[i]==0)Tarjan(i);117         printf("Case %d: ",t++);118         if(!Judge()){119             puts("No");120             continue;121         }122         puts("Yes");123         //反向建图124         memset(degree,0,sizeof(degree));125         g.clear();126         g.resize(2*n+2);127         for(int u=1;u<=2*n;u++){128             for(int i=head[u];i!=-1;i=edge[i].next){129                 int v=edge[i].v;130                 if(color[u]!=color[v]){131                     g[color[v]].push_back(color[u]);132                     degree[color[u]]++;133                 }134             }135         }136         memset(vis,0,sizeof(vis));137         TopSort();138         ans.clear();139         for(int i=1;i<=n;i++){140             if(vis[color[i]]==1)ans.push_back(i);141         }142         printf("%d",(int)ans.size());143         sort(ans.begin(),ans.end());144         for(int i=0;i<(int)ans.size();i++){145             printf(" %d",ans[i]);146         }147         puts("");148      }149     return 0;150 }
View Code

 

0 0