D36 2-SAT P5782 [POI2001] 和平委员会

视频链接:D36 2-SAT P5782 [POI2001] 和平委员会_哔哩哔哩_bilibili

 

 

 

P5782 [POI2001] 和平委员会 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

// 2-SAT+tarjan O(n+m)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=16005;
int n,m;
int head[N],idx;
struct Edge{int to,ne;}e[40005];
int dfn[N],low[N],tim,stk[N],top,scc[N],cnt;

void add(int a,int b){
  e[++idx].to=b;
  e[idx].ne=head[a];
  head[a]=idx;
}
void tarjan(int x){
  dfn[x]=low[x]=++tim;
  stk[++top]=x;
  for(int i=head[x];i;i=e[i].ne){
    int y=e[i].to;
    if(!dfn[y]){ //若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(!scc[y]) //若y已访问且未处理
      low[x]=min(low[x],dfn[y]);
  }
  
  if(low[x]==dfn[x]){ //若x是SCC的根
    ++cnt;
    for(int y=-1;y!=x;) scc[y=stk[top--]]=cnt;
  }
}
int get(int x){ //x的同党
  return (x%2)?x+1:x-1;
}    
int main(){
  scanf("%d%d",&n,&m);
  while(m--){
    int a,b;
    scanf("%d%d",&a,&b);
    add(a,get(b));
    add(b,get(a));
  }
  
  for(int i=1;i<=2*n;i++)
    if(!dfn[i]) tarjan(i);
  for(int i=1;i<=2*n;i+=2)
    if(scc[i]==scc[i+1]){
      puts("NIE");
      return 0;
    }
  for(int i=1;i<=2*n;i+=2)
    if(scc[i]<scc[i+1]) printf("%d\n",i);
    else printf("%d\n",i+1);
}

 

板子题:Problem - 3062 (hdu.edu.cn)

// 2-SAT+tarjan O(n+m)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define N 2005
int n,m;
int dfn[N],low[N],tim,stk[N],top,scc[N],cnt;
int idx,head[N];
struct Edge{
  int to,ne;
}e[4000005];

void add(int x,int y){
  e[++idx].to=y;
  e[idx].ne=head[x];
  head[x]=idx;
}
void tarjan(int x){
  dfn[x]=low[x]=++tim;
  stk[++top]=x;
  for(int i=head[x];i;i=e[i].ne){
    int y=e[i].to;
    if(!dfn[y]){ //若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(!scc[y]) //若y已访问且未处理
      low[x]=min(low[x],dfn[y]);
  }
  
  if(low[x]==dfn[x]){ //若x是SCC的根
    ++cnt;
    for(int y=-1;y!=x;) scc[y=stk[top--]]=cnt;
  }
}
int main(){
  while(~scanf("%d%d",&n,&m)){
    tim=top=cnt=idx=0;
    memset(head,0,sizeof head);
    memset(dfn,0,sizeof dfn);
    memset(stk,0,sizeof stk);
    memset(scc,0,sizeof scc);
    
    while(m--){
      int i,j,a,b;
      scanf("%d%d%d%d",&i,&j,&a,&b);
      add(i+a*n,j+!b*n);
      add(j+b*n,i+!a*n);
    }
    for(int i=0; i<2*n; i++)
      if(!dfn[i]) tarjan(i);
    bool flag=0;
    for(int i=0;i<n;i++)
      if(scc[i]==scc[i+n]){
        flag=1;break;
      }
    flag?puts("NO"):puts("YES");
  }
}

 

// 2-SAT+tarjan O(n+m)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define N 2005
int n,m;
int dfn[N],low[N],tim,stk[N],top,scc[N],cnt;
int idx,head[N];
struct Edge{
  int to,ne;
}e[4000005];

void add(int x,int y){
  e[++idx].to=y;
  e[idx].ne=head[x];
  head[x]=idx;
}
void tarjan(int x){
  dfn[x]=low[x]=++tim;
  stk[++top]=x;
  for(int i=head[x];i;i=e[i].ne){
    int y=e[i].to;
    if(!dfn[y]){ //若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(!scc[y]) //若y已访问且未处理
      low[x]=min(low[x],dfn[y]);
  }
  
  if(low[x]==dfn[x]){ //若x是SCC的根
    ++cnt;
    for(int y=-1;y!=x;) scc[y=stk[top--]]=cnt;
  }
}
int main(){
  while(~scanf("%d%d",&n,&m)){
    tim=top=cnt=idx=0;
    memset(head,0,sizeof head);
    memset(dfn,0,sizeof dfn);
    memset(stk,0,sizeof stk);
    memset(scc,0,sizeof scc);
    
    while(m--){
      int i,j,a,b;
      scanf("%d%d%d%d",&i,&j,&a,&b);
      add(2*i+a,2*j+!b); //2i妻 2i+1夫
      add(2*j+b,2*i+!a);
    }
    for(int i=0; i<2*n; i++)
      if(!dfn[i]) tarjan(i);
    bool flag=0;
    for(int i=0;i<2*n;i+=2)
      if(scc[i]==scc[i+1]){
        flag=1;break;
      }
    flag?puts("NO"):puts("YES");
  }
}

 

posted @ 2024-08-03 14:04  董晓  阅读(61)  评论(0编辑  收藏  举报