zoukankan      html  css  js  c++  java
  • UVA 11294 wedding 2-sat

    可以把一对夫妇当成一个节点,然后拆点的话,h和w分别为真和假,然后直接按照题目中说的建图染色即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    const int maxn =  100;
    const int maxm = 1000;
    struct node{
        int v,next;
    }edge[maxm];
    int res[maxm][2],head[maxn],low[maxn],dfn[maxn],stack[maxn],in[maxn],fa[maxn],ha[maxn];
    int color[maxn];
    int n,m,Time,top,scc_cnt,id;
    vector<int>DAG[maxn];
    queue<int>que;
    void add_edge(int u,int v){
        edge[id].v = v;edge[id].next = head[u]; head[u] = id++;
    }
    void init(){
        memset(head,-1,sizeof(head));
        memset(in,0,sizeof(in));
        memset(dfn,0,sizeof(dfn));
    	memset(fa,0,sizeof(fa));
        id = 0;
    	int i;
    
    	int u,v;
        char ch1,ch2;
    
        for(i = 0; i < m; i++){
            scanf("%d%c %d%c",&u,&ch1,&v,&ch2);
            u <<= 1;v <<= 1;
            if(ch1 == 'w')u ^= 1;
            if(ch2 == 'w')v ^= 1;
            //必须在一起的连边
            add_edge(u^1,v);
            add_edge(v^1,u);
        }
        //这条边必须要加
        add_edge(0,1);
    }
    int min(int x,int y){
    	return x < y ? x : y;
    }
    void tarjan(int u){//求强连通分量并缩点
        dfn[u] = low[u] = ++Time;
        stack[top++] = u;in[u] = 1;
        for(int id = head[u]; id != -1; id = edge[id].next){
            int v = edge[id].v;
            if(!dfn[v]){
                tarjan(v);
                low[u] = min(low[v],low[u]);
            }
            else if(in[v])low[u] = min(low[u],dfn[v]);
        }
        if( dfn[u] == low[u]){
            scc_cnt++;
            do{
                int v = stack[--top];
                fa[v] = scc_cnt;
                in[v] = 0;
            }while(u != stack[top]);
        }
    }
    void topsort(){//拓扑排序并着色
    	memset(color,0,sizeof(color));
        while(!que.empty()){
            int u = que.front();
            que.pop();
            if(!color[u])color[u] = 1,color[ha[u]] = 2;
            for(int i = 0; i < DAG[u].size(); i++){
                int v = DAG[u][i];
                in[v]--;
                if(!in[v])que.push(v);
            }
        }
    }
    int main(){
       // freopen("in.txt","r",stdin);
        while(~scanf("%d%d",&n,&m),n||m){
            init();
            Time = top = scc_cnt = 0;
    		int i;
            for( i = 0; i < 2*n; i++)
            if(!dfn[i])tarjan(i);
            for(i = 0; i < n; i ++)//夫妻不能做在同一边
            if(fa[i*2] == fa[i*2+1])break;
    		else {
    			ha[fa[i*2]] = fa[i*2+1];ha[fa[i*2+1]] = fa[i*2];
    		}
            if( i < n){
                puts("bad luck");
                continue;
            }
    		memset(in,0,sizeof(in));
            for( i = 1; i <= scc_cnt; i++)DAG[i].clear();
            //建反序拓扑图
            for(int u = 0; u < n*2; u++){
                for( id = head[u] ; id != -1; id = edge[id].next){
                    int v = edge[id].v;
                    if( fa[u] != fa[v]){
                        DAG[fa[v]].push_back(fa[u]);in[fa[u]]++;
                    }
                }
            }
    		while(!que.empty())que.pop();
    		for( i = 1 ; i <= scc_cnt; i++)
    			if(!in[i])que.push(i);
    		topsort();
    		//输出
            for(i = 2; i < 2*n; i += 2){
    
    			if(i!=2)printf(" ");
                if(color[fa[i]] == color[fa[0]] )printf("%dw",i/2);
                else printf("%dh",i/2);
            }
            puts("");
        }
        return 0;
    }
    

      

  • 相关阅读:
    人民币大小写转换
    window.parent与window.openner区别
    jquery.honver(),toggle()
    ADO.NET Entity Framework 之“无法加载指定的元数据资源。”
    window.external 的用法(收藏夹功能)
    空链接的技巧
    IIS自动开通组件编程
    在Asp.net中操作IIS的虚拟目录(C#)
    最佳 .NET 网站推荐
    边框 top、clientTop、scrollTop、offsetTop
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3234245.html
Copyright © 2011-2022 走看看