JOI春18 3-1 Airline Route Map <Parallel>

解説の13ページ目あたりから分岐します

Aliceパート

元のグラフを G とする。また、 i番目の頂点を G_iとする。

まず、頂点 Sを用意し、 Gの全ての頂点と結ぶ。また、頂点 B_0, B_1, ... B_{10}を用意し、 G_i kビット目が立っているならば G_i, B_kを結ぶ。 そして最後に、 B_k B_{k+1}を結ぶ。これでAliceパートは終わり f:id:ZenReKkyo:20200808153404p:plain

図示すればこのようになる。注意すべき点としては、 Sの次数が必ず Nである点と、 B_{10}の次数が必ず 1である点だ。

Bobパート

まず、頂点 Sとしてあり得る候補は次数が N=V-12である頂点のみである。(Aliceパートの作り方より、頂点数は決まる)

この候補を全て試し、矛盾が発生しないものを見つければよい。(実はここで2つ以上のグラフが発生しないとは言い切れないかも...)

 Sとそれに直接つながっている頂点を除けば、11個の頂点が出てくる。この11個だけを取り出した時、パスグラフをなせば矛盾しない。ここで、 B_{10} Sから最も遠い点であるので、そこから[B_{0}~B_{10}]まで確定させられる。 この復元はBFSを用いればできる。

あとは二進数の要領で復元し、 0~N-1まで重複なく1つずつ生成することができればよい。

コード

実装クソおもかった 微妙にTLEするが、vectorを生配列に変えるなど定数倍高速化を頑張ると通る。 atcoder.jp

#include "bits/stdc++.h"
#include "airline.h"
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define vi vector<int>
#define all(a) a.begin(),a.end()
typedef pair<int,int> P;

void Alice( int N, int M, int A[], int B[] ){
    int V=N+12;
    vi c,d;
    rep(i,M){c.push_back(A[i]);d.push_back(B[i]);}
    rep(i,N){
        c.push_back(i);d.push_back(N);
    }
    rep(i,9){
        c.push_back(N+1+i);d.push_back(N+2+i);
    }
    for(int i=0;i<N;i++){
        rep(j,10){
            if(i&(1<<j)){
                c.push_back(i);
                d.push_back(N+1+j);
            }
        }
    }
    c.push_back(N+10);d.push_back(N+11);
    int U=c.size();
    InitG(V,U);
    rep(i,U){
        MakeG(i,c[i],d[i]);
    }
}
 
const int inf=1000000000;
 
vi G[1300];
int dist[1300],dist2[1300],revM[1300],checkcnt[11];
 
void bfs(int s){
    rep(i,1300)dist[i]=inf;
    dist[s]=0;
    queue<int>Q;
    Q.push(s);
    while(Q.size()){
        int v=Q.front();Q.pop();
        for(auto e:G[v]){
            if(dist[e]>dist[v]+1){
                dist[e]=dist[v]+1;
                Q.push(e);
            }
        }
    }
}
 
void Bob( int V, int U, int C[], int D[] ){
    rep(i,U){
        G[C[i]].push_back(D[i]);
        G[D[i]].push_back(C[i]);
    }   
    int N=V-12;
    vi cand;
    rep(i,V){
        if(G[i].size()==N){
            cand.push_back(i);
        }
    }
 
    for(auto star:cand){
        unordered_map<int,int>M;
        int flg=0;
        bfs(star);
        vector<P> di2;
        int di3=-1;
        rep(i,V){
            if(dist[i]>=2){
                di2.emplace_back(P(dist[i],i));
                M[i]=inf;
            }
        }
        M[star]=N;
        sort(all(di2));
        di3=di2[10].second;
        if(di2[10].first==di2[9].first)flg++;
 
        vector<int>another[1300];
        rep(i,U){
            if(M[C[i]]==inf&&M[D[i]]==inf){
                another[C[i]].emplace_back(D[i]);
                another[D[i]].emplace_back(C[i]);
            }
        }
    
        rep(i,V)dist2[i]=inf;
        dist2[di3]=0;
        queue<int>Q;
        Q.push(di3);
        while(Q.size()){
            int v=Q.front();Q.pop();
            for(auto e:another[v]){
                if(dist2[e]>dist2[v]+1){
                    dist2[e]=dist2[v]+1;
                    Q.push(e);
                }
            }
        }
 
    rep(j,11)checkcnt[j]=0;
        rep(i,V){
            if(dist2[i]<11){
                M[i]=11-dist2[i]+N;
                checkcnt[dist2[i]]++;
            }
        }
        
        rep(j,11){
            if(checkcnt[j]!=1)flg++;
            //cerr<<checkcnt[j]<<' ';
        }
        
        if(flg)continue;
 
    //復元パート
 
        rep(i,V){
            if(dist[i]==1){
                int res=0;
                for(auto e:G[i]){
                    if(M[e]>N)res+=1<<(M[e]-N-1);
                }
                M[i]=res;
            }
        }
        
    rep(i,V)revM[i]=-1;
        rep(i,V){
            if(revM[M[i]]!=-1)flg++;
            revM[M[i]]=i;
        }
        if(flg)continue;

        vi s,t;
        rep(i,U){
            C[i]=M[C[i]],D[i]=M[D[i]];
            if(C[i]<N&&D[i]<N){
                s.push_back(C[i]);
                t.push_back(D[i]);
            }
        }
        InitMap(N,s.size());
        rep(i,s.size()){
            MakeMap(s[i],t[i]);
        }
        return;
    }
}

感想

これ本番で7人も通してるの!?ヤバ過ぎ