BZOJ1515 : [POI2006]Lis-The Postman

Claris發表於2017-02-09

首先,如果這個圖本身就不存在尤拉回路,那麼顯然無解。

對於每個子串:

1.如果裡面有不存在的邊,那麼顯然無解。

2.如果裡面有一條邊重複出現,那麼顯然也無解。

3.對於每條邊,維護其前驅與後繼,若前驅或後繼超過$1$個,那麼顯然也無解。

如此所有邊將形成一條條鏈或者環的結構,如果存在環,那麼顯然也無解。

對於每條鏈,在新圖中新增鏈頭到鏈尾的邊,然後判斷新圖中是否存在從$1$開始的尤拉回路即可。

時間複雜度$O(m\log m)$。

 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=50010,M=200010;
int n,m,q,i,j,k,pos,cnt,d[N],a[M],b[M],last[M],pre[M],nxt[M];
int g[N],V[M],W[M],NXT[M],vis[M],ed;
struct E{int x,y;}e[M];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline bool cmp(const E&a,const E&b){return a.x==b.x?a.y<b.y:a.x<b.x;}
void NIE(){puts("NIE");exit(0);}
inline int ask(int x,int y){
  int l=1,r=m,mid;
  while(l<=r){
    mid=(l+r)>>1;
    if(e[mid].x==x&&e[mid].y==y)return mid;
    if(e[mid].x<x||e[mid].x==x&&e[mid].y<y)l=mid+1;else r=mid-1;
  }
  return 0;
}
inline void add(int x,int y,int z){d[x]++,d[y]--;V[++ed]=y;W[ed]=z;NXT[ed]=g[x];g[x]=ed;}
void dfs(int x){
  for(int&i=g[x];i;){
    if(vis[i]){i=NXT[i];continue;}
    vis[i]=1;
    dfs(V[i]);
  }
}
int main(){
  read(n),read(m);
  for(i=1;i<=m;i++)read(e[i].x),read(e[i].y),d[e[i].x]++,d[e[i].y]--;
  for(i=1;i<=n;i++)if(d[i])NIE();
  sort(e+1,e+m+1,cmp);
  read(q);
  for(pos=1;pos<=q;pos++){
    read(k);
    for(i=1;i<=k;i++)read(a[i]);
    for(i=1;i<k;i++){
      b[i]=ask(a[i],a[i+1]);
      if(!b[i])NIE();
      if(last[b[i]]==pos)NIE();
      last[b[i]]=pos;
    }
    for(k--,i=1;i<k;i++){
      if(!nxt[b[i]])nxt[b[i]]=b[i+1];
      else if(nxt[b[i]]!=b[i+1])NIE();
      if(!pre[b[i+1]])pre[b[i+1]]=b[i];
      else if(pre[b[i+1]]!=b[i])NIE();
    }
  }
  for(i=1;i<=n;i++)d[i]=0;
  for(i=1;i<=m;i++)if(!pre[i]){
    for(k=0,j=i;j;j=nxt[j])a[++k]=j,cnt++;
    add(e[i].x,e[a[k]].y,a[k]);
  }
  if(cnt<m)NIE();
  if(!g[1])NIE();
  for(i=1;i<=n;i++)if(d[i])NIE();
  dfs(1);
  for(i=2;i<=n;i++)if(g[i])NIE();
  return puts("TAK"),0;
}

  

相關文章