【UVA11294】Wedding

题目描述

a184dc2d78105823fcac141994b7843124b91bc6.png
PDF

输入输出格式

输入格式:

841d3821248679dd689034bb3271bf5e8b8817c1.png

输出格式:

4a9191fdf7749cc0a395d1fd1fb465222b3ac9a2.png

输入输出样例

输入样例#1:
10 6
3h 7h
5w 3w
7h 6w
8w 3w
7h 3w
2w 5h
0 0
输出样例#1:
1h 2h 3w 4h 5h 6h 7h 8h 9h

分析

  1. 同性之间有通奸关系。由于他们不能和他们的伴侣在一边,所以我们只能让他们分别和对方的伴侣坐在一边。
  2. 异性之间有通奸关系。与第一点相同。
  3. 新娘和新郎之间连边。
  4. 一对伴侣之间不连边不会在一边。
    \(ps:\)这题改了我一个晚上,急了,直接对着标程改了。。。。。。

    代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define il inline
#define re register
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;

template<typename T>inline void read(T &x){
    T f=1;x=0;char c;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=x*10+(c^48);
    x*=f;
}

struct edge{
    int to[131],nxt[131],head[61],cnt;
    void addedge(int x,int y){
        to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
    }
}g1,g2;

int n,m;
int tot,tp,_index;
int vis[61];
int low[61],dfn[61],scc[61],stk[61],ano[61],tags[61],du[61];

void tarjan(int u){
    vis[u]=1;low[u]=dfn[u]=++_index;stk[++tp]=u;
    for(int i=g1.head[u];i;i=g1.nxt[i]){
        int v=g1.to[i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v]) low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u]){
        ++tot;
        while(stk[tp]!=u){
            scc[stk[tp]]=tot;
            vis[stk[tp]]=0;
            --tp;
        }
        scc[stk[tp]]=tot,vis[stk[tp]]=0,--tp;
    }
}

void topsort(){
    tp=0;
    for(int i=1;i<=tot;++i)
        if(!du[i])
            stk[++tp]=i;
    while(tp){
        int u=stk[tp];--tp;
        if(!tags[u]) 
            tags[u]=1,tags[ano[u]]=-1;
        for(int i=g2.head[u];i;i=g2.nxt[i]){
            int v=g2.to[i];
            --du[v];
            if(!du[v])
                stk[++tp]=v;
        }
    }
}

void Two_SAT(){
    for(int i=1;i<=n*2;++i)
        if(!dfn[i])
            tarjan(i);//2-SAT常规操作
    for(int i=1;i<=n;++i){
        if(scc[i]==scc[i+n]){
            puts("bad luck");
            return;
        }
        ano[scc[i]]=scc[i+n],ano[scc[i+n]]=scc[i];
    }
    for(int i=1;i<=n*2;++i){//缩点建新图
        for(int j=g1.head[i];j;j=g1.nxt[j]){
            int u=i,v=g1.to[j];
            if(scc[v]!=scc[u]){
                g2.addedge(scc[v],scc[u]);
                ++du[scc[u]];
            }
        }
    }
    topsort();//拓扑排序
    for(int i=1;i<n;++i)
        if(tags[scc[i]]==-1) printf("%dh ",i);
        else printf("%dw ",i);
}

int main(){
    fastio,tie0;
    int c1,c2;
    char opt1,opt2;
    while(cin>>n>>m&&n&&m){
        g1.cnt=g2.cnt=tp=tot=_index=0;
        for(int i=1;i<=n*2;++i) g1.head[i]=g2.head[i]=dfn[i]=vis[i]=du[i]=tags[i]=0;//一堆初始化
        for(int i=1;i<=m;++i){//连边
            cin>>c1>>opt1>>c2>>opt2;
            if(c1==0) c1=n;if(c2==0) c2=n;
            if(opt1=='h'&&opt2=='h') g1.addedge(c1,c2+n),g1.addedge(c2,c1+n);
            else if(opt1=='h'&&opt2=='w') g1.addedge(c1,c2),g1.addedge(c2+n,c1+n);
            else if(opt1=='w'&&opt2=='h') g1.addedge(c1+n,c2+n),g1.addedge(c2,c1);
            else g1.addedge(c1+n,c2),g1.addedge(c2+n,c1);
        }
        g1.addedge(n*2,n);//新娘和新郎
        Two_SAT();
    }
    return 0;
}

转载于:https://www.cnblogs.com/hlw1/p/11241340.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值