• HIT 1917 2—SAT


    题目大意:一国有n个党派,每个党派在议会中都有2个代表,

    现要组建和平委员会,要从每个党派在议会的代表中选出1人,一共n人组成和平委员会。

    已知有一些代表之间存在仇恨,也就是说他们不能同时被选为和平委员会的成员,

    现要你判断满足要求的和平委员会能否创立?如果能,请任意给出一种方案。( POI 0106 )

    —————————————————————————————————————————

    这道题就是裸的2—SAT

    不过我用了tarjan缩点 然后一波拓排

    tips:一个问题无解当且仅当一个集合的两个点在同一个联通块里面

    所以特判完无解之后一波拓排就可以解决问题辣

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using std::min;
    const int M=17005;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,m;
    int next(int x){return x&1?x+1:x-1;}
    struct node{int from,to,next;}e[11*M],q[11*M];
    int first[M],cnt;
    void ins(int a,int b){e[++cnt]=(node){a,b,first[a]}; first[a]=cnt;}
    int star[M],sum;
    void insq(int a,int b){q[++sum]=(node){a,b,star[a]}; star[a]=sum;}
    int dfn[M],low[M],st[M],last[M],top,tot;
    int color[M],h,in[M],op[M],ans[M];
    void tarjan(int x){
        dfn[x]=low[x]=++tot; st[++top]=x; last[x]=top;
        for(int i=first[x];i;i=e[i].next){
            int now=e[i].to;
            if(!dfn[now]) tarjan(now),low[x]=min(low[x],low[now]);
            else if(!color[now]) low[x]=min(low[x],dfn[now]);
        }
        if(dfn[x]==low[x]) for(h++;top>=last[x];top--) color[st[top]]=h;
    }
    bool f;
    void topsort(){
        std::queue<int>qu;
        for(int i=1;i<=h;i++)if(!in[i]) qu.push(i);
        while(!qu.empty()){
            int x=qu.front(); qu.pop();
            if(!ans[x]) ans[x]=1,ans[op[x]]=-1;
            for(int i=star[x];i;i=q[i].next){
                int now=q[i].to; in[now]--;
                if(!in[now]) qu.push(now);
            }
        }
    }
    void clear(){
        f=false;
        cnt=sum=h=tot=0;
        memset(color,0,sizeof(color));
        memset(last,0,sizeof(last));
        memset(dfn,0,sizeof(dfn));
        memset(st,0,sizeof(st));
        memset(low,0,sizeof(low));
        memset(in,0,sizeof(in));
        memset(first,0,sizeof(first));
        memset(star,0,sizeof(star));
        memset(op,0,sizeof(op));
        memset(ans,0,sizeof(ans));
    }
    int main(){
        int x,y;
        while(scanf("%d %d",&n,&m)==2){
            clear();
            for(int i=1;i<=m;i++) x=read(),y=read(),ins(x,next(y)),ins(y,next(x));
            for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i);
            for(int i=1;i<=n;i++)if(color[i<<1]==color[next(i<<1)]){printf("NIE
    "); f=true; break;}
            else op[color[i<<1]]=color[next(i<<1)],op[color[next(i<<1)]]=color[i<<1];
            if(f) continue;
            for(int i=1;i<=cnt;i++)if(color[e[i].from]!=color[e[i].to]) insq(color[e[i].to],color[e[i].from]),in[color[e[i].from]]++;
            topsort();
            for(int i=1;i<=n;i++)
                if(ans[color[i<<1]]==1) printf("%d
    ",i<<1); 
                else printf("%d
    ",next(i<<1)); 
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ndarray数据类型
    创建ndarray
    SqlHelper
    插入订单并且输出订单号的sql存储过程
    JQury自动切换图片
    设计模式--责任链模式
    设计模式--模板方法模式
    设计模式--观察者模式
    设计模式--享元模式
    设计模式--组合模式
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7514670.html
Copyright © 2020-2023  润新知