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