[通信題] JOI Open Contest 2017 Amusement Park

題目大意:
這是一道通信題
第一個程序 輸入一張無向圖的點和邊 再給一個2^60以內的數 第一個程序要給每個點賦值0/1
第二個程序也會讀入這張圖 然後讀入當前點編號以及當前點的值,其他點的值一律不知,每次可以調用一個函數走向一個相鄰的點,並得知這個點的值,120步以內得出只有第一個程序知道的那個數

VIEW PROBLEM - AMUSEMENT PARK (JOI17_AMUSEMENT_PARK)

做的第一道通信題,感覺這題蠻簡單,可能不習慣,搞了好久

對於一個n連通塊 可以按歐拉序走 2(n-1) 步走過所有點
隨便拎出來一個包含根的size60連通塊,要是起點在這個連通塊就直接dfs這個連通塊,不然對於其他點,必然可以搞出一個連通塊,跟他父親所在的連通塊只差一個點
每個連通塊存下六十個二進制位
每次只要走過所在連通塊就行了

代碼略醜

#include "Joi.h"
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cassert>
using namespace std;


#define V G[p].v

namespace JOI{

  const int N=10005;
  const int M=20005;

  struct edge{
    int u,v,next;  
  }G[M<<1];
  int head[N],inum=1;
  inline void add(int u,int v,int p){
    G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
  }

  const int B=60;

  int tag[M<<1];
  int fat[N],vst[N];

  inline void dfs(int u){
    vst[u]=1;
    for (int p=head[u];p;p=G[p].next)
      if (!vst[V])
    tag[p]=tag[p^1]=1,fat[V]=u,dfs(V);
  }

  struct CC{
    int idx[B+5],deg[B+5];
    bool a[B+5][B+5];
    int find(int u){ for (int i=1;i<=B;i++) if (idx[i]==u) return i; return 0;}
    void addd(int u,int v){
      u=find(u); v=find(v);
      deg[u]++; deg[v]++; a[u][v]=a[v][u]=1;
    }
  }C[N];
  int ncnt=1;

  int tot=0;
  int rt[N],ins[N];

  inline void pre(int u,int fa){
    if (tot>=B) return;
    rt[u]=1; ins[u]=1; C[1].idx[++tot]=u;
    for (int p=head[u];p;p=G[p].next)
      if (tag[p] && V!=fa)
    pre(V,u);
  }

  int clk;

  inline void build(int u,int fa){
    if (!rt[u]){
      rt[u]=++ncnt;
      C[rt[u]]=C[rt[fa]]; CC &F=C[rt[u]];
      int x;
      for (int i=1;i<=B;i++)
    if (F.deg[i]==1 && F.idx[i]!=fa){
      for (int j=1;j<=B;j++)
        if (F.a[i][j]==1)
          F.a[i][j]=0,F.a[j][i]=0,F.deg[j]--,F.deg[i]--;
      x=i; break;
    }
      F.idx[x]=u; F.addd(u,fa); 
    }
    for (int p=head[u];p;p=G[p].next)
      if (tag[p] && V!=fa)
    build(V,u);
  }

  int Idx[N];
  int w[N];
}

void Joi(int n, int m, int A[], int B[], long long X, int T) {
  using namespace JOI;
  for (int i=0;i<60;i++) w[i]=X&1,X>>=1;
  for (int i=0;i<m;i++)
    add(A[i]+1,B[i]+1,++inum),add(B[i]+1,A[i]+1,++inum);
  dfs(1);
  pre(1,0);
  for (int p=2;p<=inum;p+=2)
    if (tag[p] && ins[G[p].u] && ins[G[p].v])
      C[1].addd(G[p].u,G[p].v);
  build(1,0);
  for (int i=1;i<=n;i++){
    int tmp=Idx[i];
    Idx[i]=C[rt[i]].find(i);
    assert(tmp==0 || tmp==Idx[i]);
    MessageBoard(i-1,w[Idx[i]-1]);
  }
}

#undef V
#include "Ioi.h"
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef long long ll;

#define V G[p].v

namespace IOI{
  const int N=10005;
  const int M=20005;

  struct edge{
    int u,v,next;  
  }G[M<<1];
  int head[N],inum=1;
  inline void add(int u,int v,int p){
    G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
  }

  const int B=60;

  int tag[M<<1];
  int fat[N],vst[N];

  inline void dfs(int u){
    vst[u]=1;
    for (int p=head[u];p;p=G[p].next)
      if (!vst[V])
    tag[p]=tag[p^1]=1,fat[V]=u,dfs(V);
  }

  struct CC{
    int idx[B+5],deg[B+5];
    bool a[B+5][B+5];
    int find(int u){ for (int i=1;i<=B;i++) if (idx[i]==u) return i; return 0;}
    void addd(int u,int v){
      u=find(u); v=find(v);
      deg[u]++; deg[v]++; a[u][v]=a[v][u]=1;
    }
  }C[N];
  int ncnt=1;

  int tot=0;
  int rt[N],ins[N];

  inline void pre(int u,int fa){
    if (tot>=B) return;
    rt[u]=1; ins[u]=1; C[1].idx[++tot]=u;
    for (int p=head[u];p;p=G[p].next)
      if (tag[p] && V!=fa)
    pre(V,u);
  }

  int clk;

  inline void build(int u,int fa){
    if (!rt[u]){
      rt[u]=++ncnt;
      if (u==192)
    rt[u]=ncnt;
      C[rt[u]]=C[rt[fa]]; CC &F=C[rt[u]];
      int x;
      for (int i=1;i<=B;i++)
    if (F.deg[i]==1 && F.idx[i]!=fa){
      for (int j=1;j<=B;j++)
        if (F.a[i][j]==1)
          F.a[i][j]=0,F.a[j][i]=0,F.deg[j]--,F.deg[i]--;
      x=i; break;
    }
      F.idx[x]=u; F.addd(u,fa); 
    }
    for (int p=head[u];p;p=G[p].next)
      if (tag[p] && V!=fa)
    build(V,u);
  }

  int Idx[N],Ins[N];
  int Vst[N];
  ll Ans=0;
  int w[N];

  inline void decode(int u){
    Vst[u]=1;
    for (int p=head[u];p;p=G[p].next)
      if (tag[p] && !Vst[V] && Ins[V]){
    int d=Move(V-1); w[Idx[V]-1]=d;
    Ans+=((ll)d<<(Idx[V]-1));
    decode(V);
    Move(u-1);
      }
  }
}

long long Ioi(int n, int m, int A[], int B[], int P, int _V, int T) {
  using namespace IOI;
  for (int i=0;i<m;i++)
    add(A[i]+1,B[i]+1,++inum),add(B[i]+1,A[i]+1,++inum);
  dfs(1);
  pre(1,0);
  for (int p=2;p<=inum;p+=2)
    if (tag[p] && ins[G[p].u] && ins[G[p].v])
      C[1].addd(G[p].u,G[p].v);
  build(1,0);
  for (int i=1;i<=n;i++)
    Idx[i]=C[rt[i]].find(i);
  for (int i=1;i<=IOI::B;i++) Ins[C[rt[P+1]].idx[i]]=1;
  Ans+=((ll)_V<<(Idx[P+1]-1)); w[Idx[P+1]-1]=_V; decode(P+1);
  return Ans;
}

#undef V
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章