其他分享
首页 > 其他分享> > cogs 313. [POI2001] 和平委员会(2-SAT

cogs 313. [POI2001] 和平委员会(2-SAT

作者:互联网

http://cogs.pro:8080/cogs/problem/problem.php?pid=pyzQimjkj

题意:有n个集合,每个集合有俩元素,要从n个中各选一个放一堆,但是有的俩不能同时取,让你找出一种选取方案。

思路:2-SAT板子,主要学一下这个算法。算法流程:

构图:若a,b不能同时选,连a->b'和b->a'

求图的极大强连通子图:直接tarjan。

缩点然后变成个新的DAG:因为一个强连通分量里选一个其他都要选,一个不选其他都不能选,所以直接缩成一个点。

对新图拓排:要存反边,这个一开始不造为啥,后来看解释是因为传递的是不选择标记,这边往前代走,对面那边往后代走(对这个起作用)。。选一个他后代都得选,不选谁谁的前代都不能选,so...

自底向上进行选择,删除。

输出。

  1 #include<bits/stdc++.h>
  2 #define oth(x) x&1?x+1:x-1
  3 using namespace std;
  4 const int N = 20010;
  5 
  6 struct Edge{
  7     int to,nxt;
  8 }e[50010];
  9 int head[N],dfn[N],low[N],st[N],bel[N];
 10 bool vis[N];
 11 int ru[N],q[N],opp[N],pr[N];
 12 int tot_edge,n,nn,m,tot_node,top,cnt_block,L,R;
 13 vector<int>mp[N];
 14 
 15 
 16 inline int read() {
 17     int x = 0,f = 1;char ch = nc();
 18     for (; ch<'0'||ch>'9'; ch=nc()) if(ch=='-') f=-1;
 19     for (; ch>='0'&&ch<='9'; ch=nc()) x=x*10+ch-'0';
 20     return x * f;
 21 }
 22 void add_edge(int u,int v){
 23     e[++tot_edge].to = v;
 24     e[tot_edge].nxt = head[u];
 25     head[u] = tot_edge;
 26 }
 27 void tarjan(int u){
 28     dfn[u] = low[u] = ++tot_node;
 29     st[++top] = u;
 30     vis[u] = true;
 31     for(int i=head[u];i;i=e[i].nxt){
 32         int v = e[i].to;
 33         if(!dfn[v]){
 34             tarjan(v);
 35             low[u] = min(low[v],low[u]);
 36         }
 37         else if(vis[v])
 38             low[u] = min(dfn[v],low[u]);
 39     }
 40     if(low[u]==dfn[u]){
 41         ++cnt_block;
 42         do{
 43             vis[st[top]] = false;
 44             bel[st[top]] = cnt_block;
 45             top--;
 46         }while(st[top+1]!=u);
 47     }
 48 }
 49 void topsort(){
 50     L=1;R=0;
 51     for(int i=1;i<=cnt_block;i++){
 52         if(ru[i]==0) q[++R] = i;
 53     }
 54     while(L<=R){
 55         int u = q[L++];
 56         if(pr[u]) continue;
 57         pr[u] = 1;pr[opp[u]] = 2;
 58         int sz = mp[u].size();
 59         for(int i=0;i<sz;i++){
 60             int v = mp[u][i];
 61             ru[v]--;
 62             if(ru[v]==0) q[++R] = v;
 63         }
 64     }
 65 }
 66 bool work(){
 67     for(int i=1;i<=nn;i++){
 68         if(!dfn[i]) tarjan(i);
 69     }
 70     for(int i=1;i<=nn;i++){
 71         if(bel[i]==bel[oth(i)]) return false;
 72         opp[bel[i]] = bel[oth(i)];
 73         opp[bel[oth(i)]] = bel[i];
 74     }
 75     for(int u=1;u<=nn;u++){
 76         for(int i=head[u];i;i=e[i].nxt){
 77             int v = e[i].to;
 78             if(bel[u]!=bel[v]){
 79                 ru[bel[u]]++;
 80                 mp[bel[v]].push_back(bel[u]);
 81             }
 82         }
 83     }
 84     topsort();
 85     return true;
 86 }
 87 int main(){
 88     freopen("spo.in","r",stdin);
 89     freopen("spo.out","w",stdout);
 90     n = read(),m = read(),nn = n<<1;
 91     for(int i=1;i<=m;i++){
 92         int a = read(),b = read();
 93         add_edge(a,oth(b));
 94         add_edge(b,oth(a));
 95     }
 96     if(work()){
 97         for(int i=1;i<=nn;i++){
 98             if(pr[bel[i]]==1) cout<<i<<endl;
 99         }
100     }
101     else puts("NIE");
102     return 0;
103 }
View Code

 

标签:ch,cogs,不选,POI2001,tot,313,int,SAT
来源: https://www.cnblogs.com/wzgg/p/11409575.html