Poj P3648 Wedding___2-SAT

版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/80426154

题目大意:

给出N,从0,现在有一场宴会,可以坐两排,wife0必须做左边,husband0,其他的夫妻不能坐在同一边,给出M对通奸关系,有通奸关系的不能同时出现在wifte0的对面。
问是否存在一种可行安排方案,存在则输出可行方案的任意解。

分析:

这题真的坑啊..
题目可以转化成一道2-SAT模型,
我们设iwifei
i+nhubandi
i+2nwifei
i+n+2nhubandi

显然wife0必须要坐在左边,husband0必须坐在右边,
所以连边2n>0n>3n保证
然后将所有的夫妻wifei,husbandi(i0)连边
i>i+n+2ni+n+2n>i
i+2n>i+n,i+n>i+2n

注意同时坐在wife0一边(左边)乱搞是允许的有点怪异
所以当其中一个坐右边时另一个必须坐右边,而一个坐左边时另一个怎么选都可以。
wifeiwifej乱搞
连边i+2n>jj+2n>i
wifeihusbandj乱搞
连边i+2n>j+nj+n+2n>i
husbandihusbandj乱搞
连边i+n+2n>j+nj+n+2n>i+n
然后强连通分量判有无解,
缩点拓扑找方案即可
因为有多组数据,所以每次数组都要注意清零,
可是偏偏我用了个叫做vector的东东,
然后vector我只是clear了..而size并没有清零,所以拓扑的部分凉了..

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#define M 2000005  
#define N 2005

using namespace std; 

stack <int> st;
queue <int> Q;

struct Node { 
    int u, v, next; 
} a[M]; 
int Instack[N], Belong[N], dfn[N], low[N], Ls[N], cnt, tot, num, n, m; 
int Cp[N], Rd[N], Color[N]; 

void Addedge(int u, int v) { 
    cnt++;
    a[cnt].u = u;
    a[cnt].v = v; 
    a[cnt].next = Ls[u]; 
    Ls[u] = cnt; 
} 

void Clear_init() {
    for (int i = 0 ; i < 4 * n; i++)
         Ls[i] = Rd[i] = dfn[i] = low[i] = Color[i] = Instack[i] = 0;
    tot = num = cnt = 0;
}

void Tarjan(int u) { 
     dfn[u] = low[u] = ++num;  
     Instack[u] = 1;  
     st.push(u);  
     for (int i = Ls[u]; i; i = a[i].next) {   
          int v = a[i].v;  
          if (!dfn[v]){  
              Tarjan(v);  
              low[u] = min(low[u], low[v]);  
          }  
          else if (Instack[v]) low[u] = min(low[u], dfn[v]);  
     }   
     if (low[u] == dfn[u]) {  
          tot++;
          int rp;
          while ("rp++") {
                 rp = st.top(); 
                 st.pop();  
                 Instack[rp] = 0;  
                 Belong[rp] = tot;  
                 if (rp == u) break;
          } 
     }   
}  

void Top_sort() {
     vector <int> E[N];
     for (int i = 1; i <= cnt; i++) {
          int u =a[i].u, v = a[i].v;
          if (Belong[u] != Belong[v]) {
              E[Belong[v]].push_back(Belong[u]); 
              Rd[Belong[u]]++;
          }
       }

       for (int i = 1; i <= tot; i++)
            if (!Rd[i]) Q.push(i); 

       while (!Q.empty()) {
             int u = Q.front();
             Q.pop();
             if (!Color[u]) {
                      Color[u] = 1;      
                      Color[Cp[u]] = 2;
             }
             for (int i = 0; i < E[u].size(); i++){
                  Rd[E[u][i]]--;
                  if (!Rd[E[u][i]]) Q.push(E[u][i]);
             }
       }
}

bool solve_problem() { 
    for (int i = 0; i < 4 * n; i++) 
         if (!dfn[i]) Tarjan(i); 
    for (int i = 0; i < 2 * n; i++) { 
         if (Belong[i] == Belong[i + 2 * n]) return 0;  
         Cp[Belong[i]] = Belong[i + 2 * n];
         Cp[Belong[i + 2 * n]] = Belong[i]; 
    } 
    Top_sort(); 
    return 1; 
}

int main() {
    while (~scanf("%d %d", &n, &m)) {  
           if (!n && !m) break; 
           Clear_init();
           Addedge(2 * n, 0); 
           Addedge(n, 3 * n); 
           for (int i = 1; i < n; i++) { 
                Addedge(i, i + n + 2 * n); 
                Addedge(i + n + 2 * n, i);
                Addedge(i + 2 * n, i + n);
                Addedge(i + n, i + 2 * n);
           } 
           int x, y;
           char aa, bb;
           for (int i = 1; i <= m; i++) {
                scanf("%d%c %d%c", &x, &aa, &y, &bb); 
                if (aa == 'h') x = x + n; 
                if (bb == 'h') y = y + n; 
                Addedge(x + 2 * n, y); 
                Addedge(y + 2 * n, x); 
           }
           int count = 0;
           if (solve_problem()) { 
               for (int i = 1; i < n; i++) { 
                    if (Color[Belong[i]] == 1) { 
                        printf("%dw", i); 
                        count++; 
                        if (count != (n - 1)) printf(" "); 
                                         else printf("\n"); 
                    } else { 
                        printf("%dh", i); 
                        count++; 
                        if (count != (n - 1)) printf(" "); 
                                         else printf("\n"); 
                    } 
               } 
           } else printf("bad luck\n"); 
    } 
    return 0;
} 
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页