XJOI——NOIP2015提高组模拟题19-day1——观光旅行

http://www.hzxjhs.com:83/contest/493/problem/3

【题目大意】

给定一个有n(n<=500000)个点,m(1<=500000)条边的无向图。给Q(1<=500000)个询问ui和vi,问ui和vi之间是否存在一条不经过重复点的路径,使得经过的点数为偶数。

【题目解析】

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>

using namespace std;

#define re(i,a,b) for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)

#define SF scanf
#define PF printf
#define mmst(a,v) memset(a,v,sizeof(a))

int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxn=500000;

int n,m,Q;
int now,info[maxn+100];
struct Tedge{int v,next;}edge[2*maxn+100];
int treeedge[2*maxn+100];

void addedge(int u,int v){now++;edge[now].v=v;edge[now].next=info[u];info[u]=now;}

int dep[maxn+100],jump[maxn+100][31];
int odd[maxn+100],f[maxn+100];

void dfs(int u)
  {
      int i,j,v;
      for(i=info[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)
        if(!dep[v])
          {
              dep[v]=dep[u]+1;
              jump[v][0]=u;
              re(j,1,25)jump[v][j]=jump[jump[v][j-1]][j-1];
              treeedge[i]=treeedge[i^1]=1;
              dfs(v);
              odd[u]+=odd[v];
          }
        else
          if(!treeedge[i] && dep[u]>dep[v] && (dep[u]-dep[v])%2==0)
            {
                odd[u]++;
                odd[v]--;
            }
  }

void dfs2(int u)
  {
      int i,v;
      f[u]=f[jump[u][0]]+odd[u];
      for(i=info[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(treeedge[i] && dep[v]>dep[u])dfs2(v);
  }

void swim(int &x,int H){int i;for(i=0;H!=0;H>>=1,i++)if(H&1)x=jump[x][i];}
int ask_lca(int x,int y)
  {
      if(dep[x]<dep[y])swap(x,y);
      swim(x,dep[x]-dep[y]);
      if(x==y)return x;
      int j;
      red(j,25,0)if(jump[x][j]!=jump[y][j])x=jump[x][j],y=jump[y][j];
      return jump[x][0];
  }

int main()
  {
      freopen("travel.in","r",stdin);
      freopen("travel.out","w",stdout);
      int i,j;
      n=gint();m=gint();Q=gint();
      now=-1;mmst(info,-1);
      re(i,1,m)
        {
            int x=gint(),y=gint();
            addedge(x,y);addedge(y,x);
        }
      dep[1]=1;
      re(j,0,25)jump[1][j]=1;
      dfs(1);
      re(i,1,n)if(odd[i])odd[i]=1;
      dfs2(1);
      while(Q--)
        {
            int x=gint(),y=gint();
                int lca=ask_lca(x,y);
                if((dep[x]-dep[lca]+dep[y]-dep[lca])%2==1 || f[x]-f[lca]>=1 || f[y]-f[lca]>=1)PF("TAK\n");else PF("NIE\n");
            }
        return 0;
    }
View Code

 

posted @ 2015-11-11 08:54  maijing  阅读(378)  评论(0编辑  收藏  举报