POJ 3648 Wedding (Tarjan + 缩点 + 拓扑排序)

来源:互联网 发布:淘宝代办签证靠谱吗 编辑:程序博客网 时间:2024/05/18 19:22

题目链接:

http://poj.org/problem?id=3648

题解:

2-SAT问题,不过我用Tarjan + 缩点 + 拓扑排序做的。。。这样可以输出一组可行解,但是我不知道怎么输出字典树最小的解。。比较尴尬。

AC代码:

#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <cstring>#include <stack>#include <queue>using namespace std;vector <int> mapp[10000];vector <int> remap[10000];int dfn[10000],low[10000],stk[10000],vis[10000],color[10000],conflict[10000],col[10000],degree[10000];int cnt,t,sig;int n,m,a,b,x1,y1,x2,y2;char c,d;void init(){    memset(vis,0,sizeof(vis));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(color,0,sizeof(color));    memset(stk, 0, sizeof(stk));    memset(conflict, 0, sizeof(conflict));    memset(col, 0, sizeof(col));    memset(degree, 0, sizeof(degree));    for(int i=1;i<=2*n;i++)    {        mapp[i].clear();        remap[i].clear();    }}void Tarjan(int u){    vis[u] = 1;    low[u] = dfn[u] = cnt++;    stk[++t] = u;    for(int i = 0; i < mapp[u].size(); i++)    {        int v = mapp[u][i];        if(!vis[v]) Tarjan(v);        if(vis[v] == 1) low[u] = min(low[u],low[v]);    }    if(dfn[u] == low[u])    {        sig++;        do        {            color[stk[t]] = sig;            vis[stk[t]] = -1;        }        while(stk[t--] != u);    }}void rebuild()//反向构图{    for(int i=1;i <= 2*n;i++)    {        for(int j=0;j< mapp[i].size();j++)        {            int v = mapp[i][j];            if(color[i] != color[v])            {                degree[color[i]]++;                remap[color[v]].push_back(color[i]);            }        }    }}void topsort(){    queue<int> qq;    for(int i = 1 ;i <= sig;i++)    {//现在对缩点后的图进行拓扑        if(!degree[i])        {            qq.push(i);        }    }    while(!qq.empty())    {        int u = qq.front();        qq.pop();        if(!col[u])        {            col[u] = 1;//红色            col[conflict[u]] = 2;//蓝色(因为缩点后变成有向无环图,对应的冲突点只有确定的一个)        }        for(int i=0;i<remap[u].size();i++)        {            int vv = remap[u][i];            degree[vv]--;            if(!degree[vv])qq.push(vv);        }    }}int main(){    while(~scanf("%d %d", &n, &m) && (n+m))    {        init();        for(int i = 1; i <= m; i++)        {            int x,y;            scanf("%d%c %d%c", &x, &c, &y, &d);            if(c == 'h')            {                x1 = 2*x+2;//man                y1 = 2*x+1;//woman            }            else            {                x1 = 2*x+1;//woman                y1 = 2*x+2;//man            }            if(d == 'h')            {                x2 = 2*y+2;//man                y2 = 2*y+1;//woman            }            else            {                x2 = 2*y+1;//woman                y2 = 2*y+2;//man            }            mapp[x1].push_back(y2);            mapp[x2].push_back(y1);        }        mapp[1].push_back(2);        cnt = 1, t = -1, sig = 0;        for(int i = 1; i <= 2 * n; i++)        {            if(!vis[i])                Tarjan(i);        }       // for(int i = 1; i <= 2 * n; i++)          //  cout << i << " " <<color[i] <<endl;        bool flag=true;        for(int i = 0; i < n; i++ )        {            if(color[2*i + 1]==color[2*i + 2])            {                flag=false;                break;            }        }        if(flag)        {            for(int i = 1 ; i <= 2*n;i+=2)            {                int aa = color[i],bb = color[i+1];                conflict[aa] = bb;                conflict[bb] = aa;            }            rebuild();            topsort();            //for(int i = 0; i <= 2*n; i++)             //   cout << col[i] <<endl;            for(int i=3; i<= 2*n; i+=2)            {                if(i!=3)                    printf(" ");                if(col[color[i]] == col[color[1]])                    printf("%dw",i/2);                else                    printf("%dh",i/2);//否则,取她的老公            }            puts("");        }        else            puts("bad luck");    }}
0 0
原创粉丝点击