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\n"); 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\n",i<<1);
            else printf("%d\n",next(i<<1));
    }
    return 0;
}

时间: 2024-10-24 07:17:23

HIT 1917 2—SAT的相关文章

2-SAT入门

大概学了一下2-SAT,写了一道模板和一道USACO 输出一个方案的话,tarjan缩点后倒着拓扑,染色输出. 求任何解下选哪个就得枚举每个点dfs来判断选哪个. HIT 1917(2-sat模板) #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<

LA 3211 飞机调度(2—SAT)

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

区间素数个数 树状数组 HIT 1867 经理的烦恼

http://acm.hit.edu.cn/hoj/problem/view?id=1867 经理的烦恼   Source : HCPC 2005 Spring   Time limit : 2 sec   Memory limit : 32 M Submitted : 2994, Accepted : 686 Jerry是一家公司销售部门的经理.这家公司有很多连锁店,编号为1,2,3,... Jerry每天必须关注每家连锁店的商品数量及其变化,一项很乏味的工作.在连锁店比较少的时候,Jerry

Hit 2255 Not Fibonacci

今天下午刚起来眼睛就比较涨,,而且还有点恶心,唉,结果一直不在状态,而且这个题太坑了.... 点击此处即可传送 Hit 2255 Maybe ACMers of HIT are always fond of fibonacci numbers, because it is so beautiful. Don't you think so? At the same time, fishcanfly always likes to change and this time he thinks abo

POJ 1917

http://poj.org/problem?id=1917 poj的字符串的一道水题. 题意么无关紧要, 反正输出的第一行就是把那个<>去掉,s1<s2>s3<s4>s5, 也就是第一行就是输出s1s2s3s4s5就行. 第二行就是输出s1s4s3s2s5就可以. 1 #include <stdio.h> 2 #include <string.h> 3 4 char str[2][110]; 5 6 int main() 7 { 8 int n

Html5 Canvas Hit Testing

名词解释: Shape : 矢量图形,点线面之类的: Hit Testing : 点击测试: 参考内容: A Gentle Introduction to Making HTML5 Canvas Interactive 小记: 在Html5中使用Canvas对象来绘制矢量图形Shape,我们希望对这些Shape对象做更进一步的操作,如选中.拖拽等,那么必然我们需要在Canvas上有一个Hit Testing ,遗憾的是Canvas并没有提供对内置对象Hit Testing的方法.(W3C.Org

8.3吝啬SAT问题

吝啬SAT问题是这样的:给定一组子句(每个子句都是其中文字的析取)和整数k,求一个最多有k个变量为true的满足赋值--如果该赋值存在.证明吝啬SAT是NP-完全问题. 1.易知吝啬SAT的解可以在多项式时间内验证,因此属于NP问题. 2.如果我们把吝啬SAT问题中的k设置为输入的数目,那么SAT问题就可以规约到吝啬SAT问题,所以吝啬SAT问题是np-完全问题.

Design Hit Counter

Design a hit counter which counts the number of hits received in the past 5 minutes. Each function accepts a timestamp parameter (in seconds granularity) and you may assume that calls are being made to the system in chronological order (ie, the times

LeetCode &quot;Design Hit Counter&quot;

Hits come and go - so we use queue. Nothing special. class HitCounter { queue<int> q; public: /** Initialize your data structure here. */ HitCounter() { } /** Record a hit. @param timestamp - The current timestamp (in seconds granularity). */ void h