lightOJ 1251 - Forming the Council(2-sat)

来源:互联网 发布:暴风影音mac版使用说明 编辑:程序博客网 时间:2024/06/07 03:25

题意:n个人参与投票,被选的人有m个,每一个人都有两个选择:让某个人当选,让某个人下台。。问是否存在一个方式,能够每一个选民的至少一个选择。

思路:如果一个人的第一个选择没有被满足,则另一个选择一定要被满足、


#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <iostream>#include <queue>#include <stack>using namespace std;const int N = 20009;const int M = 8009;struct LT{    int nex,to;} L[N<<2];int F[M<<1],cnt;void add(int f,int t){    L[cnt].nex = F[f];    L[cnt].to = t;    F[f] = cnt++;}struct ET{    int nex,to;} EL[N<<2];int EF[M<<1],Ecnt;void Eadd(int f,int t){    EL[Ecnt].nex = EF[f];    EL[Ecnt].to = t;    EF[f] = Ecnt++;}int n,m;void init(){    memset(F,0,sizeof(F));    memset(EF,0,sizeof(EF));    cnt = 1;    Ecnt  = 1;}int dfn[M<<1],col[M<<1],low[M<<1],post[M<<1],ind,color;stack<int> S;void tarjan(int k){    low[k] = dfn[k] = ind++;    S.push(k),post[k] = 1;    for(int i=F[k];i;i=L[i].nex)    {        int to = L[i].to;        if(!dfn[to])        {            tarjan(to);            low[k] = min(low[to],low[k]);        }else if(post[to]&&dfn[to]<low[k])        low[k] = dfn[to];    }    if(low[k]==dfn[k])    {        int i;color++;        for(i=S.top(),S.pop();i!=k;i=S.top(),S.pop())        {            post[i] = 0,col[i] = color;            Eadd(color,i);        }        Eadd(color,i);        post[i] = 0,col[i] = color;    }}void solve(){    ind = 1,color = 0;    memset(low,0,sizeof(low));    memset(dfn,0,sizeof(dfn));    for(int i=0;i<(m<<1);i++)    if(!dfn[i]) tarjan(i);    for(int i=0;i<m;i++)    if(col[i]==col[i+m])    {        printf("No\n");        return ;    }    printf("Yes\n");    int ans[M];    memset(ans,-1,sizeof(ans));    for(int i=1;i<=color;i++)    if(ans[i]==-1)    for(int j=EF[i];j;j=EL[j].nex)    {        ans[i] = 1;        ans[col[(EL[j].to+m)%(m<<1)]] = 0;    }    int out[M],tmp=0;    for(int i=0;i<m;i++)    if(ans[col[i]]==1)    {        out[tmp++] = i+1;    }    printf("%d",tmp);    for(int i=0;i<tmp;i++)    printf(" %d",out[i]);    printf("\n");}int main(){    freopen("in.txt","r",stdin);    int cas,T =1;    scanf("%d",&cas);    while(cas--)    {        scanf("%d%d",&n,&m);        int a,b,a1,b1;        init();        for(int i=0;i<n;i++)        {            scanf("%d%d",&a,&b);            if(a<0) a = m-a;            if(b<0) b = m-b;            a--;b--;            a1 = (a+m) %(m<<1);            b1 = (b+m) %(m<<1);            add(a1,b);            add(b1,a);        }        printf("Case %d: ",T++);        solve();    }    return 0;}