[BZOJ3495][PA2010][2-SAT]Riddle

明显的2-SAT模型,但是对于国家的限制,边数是 O(n2) 的。
可以考虑对有x个城市的国家新建x个结点,第i个结点表示1~i的结点中是否存在首都。那么边数就可以优化到 O(n)

#include 
#include 
#include 
#define N 1000010
#define M 5000100

using namespace std;

int n,m,k,cnt,g,tms;
int A[N],B[N];
int G[M],flg[M],low[M],dfn[M],vis[M],stk[M],top;
struct edge{
  int t,nx;
}E[M<<2];

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void rea(int &x){
  char c=nc(); x=0;
  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

inline void Insert(int x,int y){
  E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;
}

void tarjan(int x){
  dfn[x]=low[x]=++tms;
  stk[++top]=x;
  vis[x]=1;
  for(int i=G[x];i;i=E[i].nx)
    if(!vis[E[i].t]) tarjan(E[i].t),low[x]=min(low[x],low[E[i].t]);
    else if(vis[E[i].t]==1) low[x]=min(low[x],dfn[E[i].t]);
  if(low[x]==dfn[x]){
    ++*flg;
    while(1){
      int u=stk[top]; top--;
      flg[u]=*flg;
      vis[u]=2;
      if(u==x||!top) break;
    }
  }
}

int main(){
  rea(n); rea(m); rea(k); g=n;
  for(int i=1;i<=m;i++){
    int x,y; rea(x); rea(y);
    Insert(x<<1|1,y<<1);
    Insert(y<<1|1,x<<1);
  }
  for(int i=1;i<=k;i++){
    int t; rea(t);
    for(int j=1;j<=t;j++) rea(A[j]),B[j]=++g;
    for(int j=1;j1,B[j+1]<<1);
    for(int j=2;j<=t;j++) Insert(B[j]<<1|1,B[j-1]<<1|1),Insert(B[j-1]<<1,A[j]<<1|1),Insert(A[j]<<1,B[j-1]<<1|1);
    for(int j=1;j<=t;j++) Insert(A[j]<<1,B[j]<<1),Insert(B[j]<<1|1,A[j]<<1|1);
  }
  for(int i=2;i<=(g<<1|1);i++)
    if(!vis[i]) tarjan(i);
  for(int i=1;i<=g;i++)
    if(flg[i<<1]==flg[i<<1|1]) return puts("NIE"),0;
  return puts("TAK"),0;
}


你可能感兴趣的:(2-SAT)