• P3007 [USACO11JAN]大陆议会The Continental Cowngress


    P3007 [USACO11JAN]大陆议会The Continental Cowngress

    题意: 给出 n 个法案, m 头牛的意见, 每头牛有两个表决 格式为 “支持或反对某法案”, 每头牛需要至少满足一个表决, 不可能成立的话输出 IMPOSSIBLE, 否则输出方案, Y代表能, N代表不能若是有的解中法案可以通过, 有些不能则输出“?”


    哇这题确认过眼神, 遇上对的测评机莫名洛谷 (RANK 1)

    首先若是没有输出 (?) 这题就是一个裸的 限制条件为或(2-SAT), 关键是我们如何处理这个 “可以在不同的解中为不同的状态”

    回想一下在2-SAT里提到过的 ** (Tarjan) 的过程就是逻辑推理的过程 ,** 若是点 (v) 能由 (u) 到达, 那我们认为 **满足意义 (u) 则一定需要满足意义 (v) ** , 那么我们很快就可以得到啥时候一个条件的两个状态((0)(1))没得关系了: (u , v) 两点不互达时, 他们之间无明确的互相限制关系

    所以在确定有解以后, 我们在 (Tarjan) 后的 (DAG) 上对于一个法案的两种状态 (dfs) , 若不互通则此点状态任意
    p.s:因为是 (DAG) 所以不用 (vis[ ])数组
    p.s.s:别忘了建新图的时候别搞自环。。。

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    typedef long long LL;
    using namespace std;
    int RD(){
        int out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const int maxn = 2000019,INF = 1e9 + 19;
    int head[maxn][2],nume = 1;
    struct Node{
        int v,dis,nxt;
        }E[maxn << 2][2];
    void add(int u,int v,int dis, int o){
        E[++nume][o].nxt = head[u][o];
        E[nume][o].v = v;
        E[nume][o].dis = dis;
        head[u][o] = nume;
        }
    int num, nr;
    int DFN[maxn], LOW[maxn], INDEX;
    int S[maxn], top;
    bool ins[maxn];
    int col[maxn], numc;
    void Tarjan(int u){
    	DFN[u] = LOW[u] = ++INDEX;
    	S[++top] = u;ins[u] = 1;
    	for(int i = head[u][0];i;i = E[i][0].nxt){
    		int v = E[i][0].v;
    		if(!DFN[v])Tarjan(v), LOW[u] = min(LOW[u], LOW[v]);
    		else if(ins[v])LOW[u] = min(LOW[u], DFN[v]);
    		}
    	if(DFN[u] == LOW[u]){
    		numc++;
    		while(S[top + 1] != u){
    			col[S[top]] = numc;
    			ins[S[top--]] = 0;
    			}
    		}
    	}
    bool dfs(int u, int goal){
    	if(u == goal)return 1;
    	for(int i = head[u][1];i;i = E[i][1].nxt){
    		int v = E[i][1].v;
    		if(dfs(v, goal))return 1;
    		}
    	return 0;
    	}
    bool check(int c1, int c2){
    	if(!dfs(c1, c2) && !dfs(c2, c1)){
    		printf("?");
    		return 1;
    		}
    	return 0;
    	}
    int main(){
    	num = RD();nr = RD();
    	int a, b, x, y;char c1, c2;
    	for(int i = 1;i <= nr;i++){
    		a = RD(), cin>>c1, b = RD(), cin>>c2;
    		if(c1 == 'Y')x = 1;else x = 0;
    		if(c2 == 'Y')y = 1;else y = 0;
    		//<< 1 | 0 -> 0 , << 1 | 1 -> 1
    		add(a << 1 | (x ^ 1), b << 1 | y, 1, 0);
    		add(b << 1 | (y ^ 1), a << 1 | x, 1, 0);
    		}
    	for(int i = 2;i <= (num << 1 | 1);i++)if(!DFN[i])Tarjan(i);
    	for(int i = 1;i <= num;i++){
    		if(col[i << 1] == col[i << 1 | 1]){
    			puts("IMPOSSIBLE");
    			return 0;
    			}
    		}
    	for(int u = 2;u <= (num << 1 | 1);u++){
    		for(int i = head[u][0];i;i = E[i][0].nxt){
    			int v = E[i][0].v;
    			if(col[u] == col[v])continue;
    			add(col[u], col[v], 1, 1);
    			}
    		}
    	for(int i = 1;i <= num;i++){
    		if(check(col[i << 1], col[i << 1 | 1]))continue;
    		if(col[i << 1] < col[i << 1 | 1])printf("N");
    		else printf("Y");
    		}
    	puts("");
    	return 0;
    	}
    
  • 相关阅读:
    揆首:以极客的思维做云诺
    [置顶] iOS学习笔记47——图片异步加载之EGOImageLoading
    wxWidgets初学者导引(3)——wxWidgets应用程序初体验(PDF版及附件下载)
    Win7 下用 VS2015 编译最新 openssl(1.0.2j)包含32、64位debug和release版本的dll、lib(8个版本)
    十问华为战略营销总裁徐文伟
    Debug与Release有时候确实不一致
    COM实践经验
    [置顶] (游戏编程-04)JAVA版雷电(奇迹冬瓜)
    第23章 COM和ActiveX(COM可以实现跨进程跨机器的函数调用)
    用Delphi即时判断当前的网络的连接方式
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9461406.html
Copyright © 2020-2023  润新知