题目大意:
这是一道通信题
第一个程序 输入一张无向图的点和边 再给一个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