您的位置:首页 > 其它

poj 3648 wedding(2-sat 拓扑排序输出方案)

2015-08-25 19:32 483 查看
题意怪怪的,还不给输入规模_(:3 」∠)_,听说数据也是水的。难怪没有把边反向也可以过。。

n对夫妇,从0开始编号,其中0号为新郎和新娘,分别坐在两端。给出m对关系(i,j),i和j不能一起坐在新娘对面,这n对夫妇中任意一对不能坐在同一端。输出与新娘在同一端的其他n-1个人。

建图:

首先将0(新娘)和新郎(1)连一条边,表示新娘和新郎必须坐在不同端。

然后对于关系(i,j),连接 2i->2j+1,2j->2i+1,表示i和j的配偶必然坐于同一端,j和i的配偶也必然坐于同一端。

然后SCC缩点,若有解,则反向建边后进行拓扑排序求出方案。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
#define maxn 2005
#define maxm 1000005

vector<int> G[maxn];
int pre[maxn],low[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> S;

void dfs(int u){
    pre[u]=low[u]=++dfs_clock;
    S.push(u);
    for(int i=0;i<(int)G[u].size();++i){
        int v=G[u][i];
        if(!pre[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);//用后代的low函数更新自身
        }
        else if(!sccno[v]){
            low[u]=min(low[u],pre[v]);//用反向边更新
        }
    }
    if(low[u]==pre[u]){
        ++scc_cnt;
        for(;;){
            int x=S.top();S.pop();
            sccno[x]=scc_cnt;
            if(x==u) break;
        }
    }
}

void find_scc(int n){
    dfs_clock=scc_cnt=0;
    memset(sccno,0,sizeof(sccno));
    memset(pre,0,sizeof(pre));
    for(int i=0;i<n;++i)
        if(!pre[i]) dfs(i);
}
int L[maxm],R[maxm],rsccno[maxn];
int n,m;
int col[maxn],in[maxn];
vector<int> G2[maxn];
void tpsort(int tot)
{
    memset(col,-1,sizeof(col));
    queue<int> q;
    for(int i=1;i<=tot;++i) if(!in[i]) q.push(i);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        if(col[u]!=-1) continue;
        col[u]=0;col[rsccno[u]]=1;
        for(int i=0;i<(int)G2[u].size();++i)
            {
                --in[G2[u][i]];
                if(!in[G2[u][i]]) q.push(G2[u][i]);
            }
    }
}

int main()
{
    int j,i;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m) break;
        for(i=0;i<2*n;++i) G[i].clear();
        G[0].push_back(1);
        for(i=0;i<m;++i)
        {
            int A,B;
            char a,b;
            scanf("%d%c%d%c",&L[i],&a,&R[i],&b);
            A=a=='h'?1:0;
            B=b=='h'?1:0;
            G[2*L[i]+A].push_back(2*R[i]+1-B);
            G[2*R[i]+B].push_back(2*L[i]+1-A);
        }
        find_scc(n<<1);

        for(i=0;i<n;++i)
            if(sccno[i<<1]==sccno[i<<1|1]) break;
            else{
                rsccno[sccno[i<<1]]=sccno[i<<1|1];
                rsccno[sccno[i<<1|1]]=sccno[i<<1];
            }
        if(i<n) puts("bad luck");
        else{
            memset(in,0,sizeof(in));
            for(i=1;i<=scc_cnt;++i) G2[i].clear();
            for(i=0;i<(n<<1);++i)
                for(j=0;j<(int)G[i].size();++j)
                    if(sccno[i]!=sccno[G[i][j]]){
                        ++in[sccno[G[i][j]]];
                        G2[sccno[i]].push_back(sccno[G[i][j]]);
                    }
            tpsort(scc_cnt);
            int color=col[sccno[0]];
            for(i=1;i<n;++i){
                if(i!=1) putchar(' ');
                if(col[sccno[i<<1]]==color) printf("%dw",i);
                else printf("%dh",i);
            }
            puts("");
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: