一个菜菜的蜕变之路?

时间是个常数,也是个变数

Poj P3648 Wedding___2-SAT

题目大意:

给出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;
} 
阅读更多
版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/80426154
想对作者说点什么? 我来说一句

poj各种分类

2011年09月21日 150KB 下载

北大ACM 题目分类

2010年07月21日 111KB 下载

poj 1012解题报告

2010年04月02日 3KB 下载

poj 1659解题报告

2010年04月07日 4KB 下载

poj 3720解题报告

2010年04月07日 2KB 下载

POJ题目分类 POJ题目分类

2010年04月03日 107KB 下载

poj 2329解题报告

2010年04月02日 5KB 下载

poj 3414解题报告

2010年04月02日 8KB 下载

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

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭