UVALive-4452 The Ministers' Major Mess (2-SAT)

题目大意:有n个问题,m个人来投票,没人最多投4票,问该怎样决定才能使每个人都有超过一半的票数被认可?

题目分析:2-SAT问题。如果某个人投的票数少于2,则这两票军被采纳,如果票数至少三票,则最多有一票可以不被采纳,这意味着这个人的投的任意两票之间有矛盾,是“二者取一”的关系。

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;
# define LL long long
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CLS(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b)

const int N=105;
vector<int>G[N<<1];
int n,m,a[5],b[5],must[N+N],mark[N+N],flag[N],s[N+N],cnt;

void add(int x,int u,int y,int v)
{
    x=x*2+u;
    y=y*2+v;
    G[x^1].push_back(y);
    G[y^1].push_back(x);
}

void dfs1(int u)
{
    must[u]=1;
    REP(i,0,G[u].size()) if(!must[G[u][i]]) dfs1(G[u][i]);
}

void clear()
{
    CLS(mark,0);
    REP(i,0,n+n) mark[i]=must[i];
}

bool dfs(int x)
{
    if(mark[x^1]) return false;
    if(mark[x]) return true;
    mark[x]=1;
    s[cnt++]=x;
    REP(i,0,G[x].size()) if(!dfs(G[x][i])) return false;
    return true;
}

bool solve()
{
    for(int i=0;i<n+n;i+=2){
        if(mark[i]&&mark[i+1]) return false;
        if(!mark[i]&&!mark[i+1]){
            cnt=0;
            if(!dfs(i)){
                while(cnt>0) mark[s[--cnt]]=0;
                if(!dfs(i+1)) return false;
            }
        }
    }
    return true;
}

void init()
{
    REP(i,0,n*2) G[i].clear();
    CLS(must,0);
    CLS(mark,0);
}

int main()
{
    int k,cas=0;
    char c;
    while(scanf("%d%d",&n,&m)&&(n+m))
    {
        init();
        CLS(flag,0);
        while(m--)
        {
            scanf("%d",&k);
            REP(i,0,k){
                scanf("%d %c",&a[i],&c);
                --a[i];
                if(c==‘y‘) b[i]=1;
                else b[i]=0;
            }
            if(k<=2){
                REP(i,0,k) must[a[i]*2+b[i]]=1;
            }else
                REP(i,0,k) REP(j,i+1,k) add(a[i],b[i],a[j],b[j]);
        }

        REP(i,0,n+n) if(must[i]) dfs1(i);

        printf("Case %d: ",++cas);
        REP(i,0,n){
            if(must[i*2]||must[i*2+1]) continue;
            clear();
            mark[i*2]=1;
            bool yy1=solve();
            clear();
            mark[i*2+1]=1;
            bool yy2=solve();
            if(yy1&&yy2) flag[i]=1;
        }
        clear();
        if(!solve()){
            printf("impossible\n");
            continue;
        }
        REP(i,0,n){
            if(flag[i]) printf("?");
            else if(mark[i*2]) printf("n");
            else printf("y");
        }
        printf("\n");
    }
    return 0;
}

  

UVALive-4452 The Ministers' Major Mess (2-SAT)

时间: 2024-10-10 09:38:55

UVALive-4452 The Ministers' Major Mess (2-SAT)的相关文章

UVALive - 4452 The Ministers&#39; Major Mess(2-SAT)

题目大意:有n个人对m个方案投票,每个人最多只能对其中的4个方案投票(其他的相当于弃权),每一票要么支持要么反对.问是否存在一个最终决定,使得每个投票人都有超过一半的建议被采纳,在所有可能的最终决定中,哪些方案的态度是确定的 解题思路:参考了一下别人的思路,学习了 当想要确定某一个状态(i)时,可以用他的相反状态(i^1)和该状态建立一条边,那样的话,每当dfs到他的相反状态时,就会return false 在理解了上面的基础上,就可以建边了 首先,要有超过一半的投票被采纳.也就是说,当投票数小

UVA 1086 - The Ministers&#39; Major Mess(2-sat)

UVA 1086 - The Ministers' Major Mess 题目链接 题意:有n个方案,每个人投票,一个人最多投4张票,现在要有一个方案,使得满足所有人投票方案中有超过一半被满足,输出方案的对错,如果一个方案对错都可以,就输出? 思路:明显是二分图,一开始想错了,想从正着去把条件式化简,根本不可行 正确的做法是,反过来想,因为最多4张票并且超过1半,如果反过来想选哪些方案不满足,那么就只有1和0的情况,就很容易构造表达式了,然后就是2-sat,对于?的情况,只要遍历一遍,每个位置再

UVALive 5966 Blade and Sword -- 搜索(中等题)

题意:给一幅地图,P为起点,D为终点,'*'为传送阵,到达传送阵可以传到任意一个其他的传送阵,传到以后可以正常走或者再传回来,问P->D最短步数. 分析:这题一定要细心,分析要到位才能搞定,错一点都WA.有两种思路: 1.走到一个传送点之后,将所有能传到的地方都加入队列,然后清除传送阵向量(vector),因为以后不用再互相传了,对于某个传送阵k,以后从别的点传到k的效果还不如从这个点传到k,所以清空传送阵,又因为其他传送阵可以传回来,此时传送阵向量要把当前传送阵push_back进去,以便其他

UVa 1225 / UVALive 3996 Digit Counting 数数字(字符统计)

Digit Counting Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Trung is bored with his mathematics homeworks. He takes a piece of chalk and starts writing a sequence of consecutive integers starting

(2 sat) hdu 1824

Let's go home Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1523    Accepted Submission(s): 616 Problem Description 小时候,乡愁是一枚小小的邮票,我在这头,母亲在那头.                        —— 余光中 集训是辛苦的,道路是坎坷的,休息还是

LA 3211 飞机调度(2—SAT)

https://vjudge.net/problem/UVALive-3211 题意: 有n架飞机需要着陆,每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种,第i架飞机的早着陆时间为E,晚着陆时间为L,不得在其他时间着陆.你的任务是为这些飞机安排着陆方式,使得整个着陆计划尽量安全.换句话说,如果把所有飞机的实际着陆时间按照从早到晚的顺序排列,相邻两个着陆时间间隔的最小值. 思路: 二分查找最大值P,每次都用2—SAT判断是否可行. 1 #include<iostream>

(2 sat) poj 2723

Get Luffy Out Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7758   Accepted: 2969 Description Ratish is a young man who always dreams of being a hero. One day his friend Luffy was caught by Pirate Arlong. Ratish set off at once to Arlo

命令说明(混乱版)第一周

命令  bc 是任意精度计算器语言 在linux下当计算器用选项值-i:强制进入交互式模式:-l:定义使用的标准数学库-w:对POSIX bc的扩展给出警告信息:-q:不打印正常的GNU bc环境信息:-v:显示指令版本信息:-h:显示指令的帮助信息.常用运算: 加法- 减法* 乘法/ 除法^ 指数% 余数 cat 链接文件并打印到标准输出设备上 type 用于显示指定命令的类型,判断给出的指令是内部还是外部如果给出的恢复是 XX is a shell builtin 是内建命令-a 显示 指令

UVALive - 3641 Leonardo&#39;s Notebook(polya计数)

题意:给出26个大写字母的置换B,问是否存在一个置换A,使A*A=B? 两个长度为N的相同循环相乘,当N为奇数时结果也是一个长度为N的循环,当N为偶数时分裂为两个长度为N/2的循环.相反,对于一个任意长度为N的奇数循环B,都能找到一个长度为N的循环A使得A*A=B,对于任意两个长度为N(N不一定为偶数)的不相交循环B和C,都能找到一个长度为2N的循环A使得A*A=B*C. 于是只要判断置换B里循环长度相同的且都为偶数(2,4,6, 8.....)的循环个数是不是都为偶数(偶数就能两两配对),只要