題目大意:
這是一道通信題
第一個程序 輸入一張無向圖的點和邊 再給一個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