标签:rp int 题解 pb Nav go return FARIO2019 mx
交互题,给定一张 \(n\) 个点无向图,进行 \(k\) 局游戏,每局先初始化一个点 \(x\),选手每次询问一个点 \(u\),返回 \(u\) 到 \(x\) 某条最短路上的某条边。需要在 \(9\) 次操作内求出点 \(x\)。\(n\le 300,k\le 750\)。
对于一条链的情况,可以直接二分。一棵树的情况可以直接点分治。
那么对于图的情况,我们求出每个点出发的最短路图,对这个 DAG 求出最劣情况下能排除多少个点,然后取最优的 DAG 分治。
结论,每次取最优的 DAG,决策集合至少减半。还不太会证明。
先 Floyd 求任意两点最短路,每次询问及时更新决策集合与 DAG。复杂度是 \(\mathcal{O}(n^3 + k(n^2 + m\log n))\)。
int n, d[N][N];
int nav(int);
vector<int>e[N];
vector<Pr>o;
void init(int subtask, int n_, int m, std::vector<int> A, std::vector<int> B) {
n = n_; memset(d, 0x3f, sizeof(d));
o.resize(m);
rep(i, 0, m - 1){
A[i] ++, B[i] ++, o[i] = {A[i], B[i]};
d[A[i]][B[i]] = d[B[i]][A[i]] = 1;
e[A[i]].pb(B[i]), e[B[i]].pb(A[i]);
}
rp(i, n)d[i][i] = 0;
rp(k, n)rp(i, n)rp(j, n)cmn(d[i][j], d[i][k] + d[k][j]);
}
vector<int>c;
int calc(){
if(si(c) == 1)return c[0] - 1;
int mn = inf, u = ~0;
go(x, c){
int mx = 0;
go(y, e[x]){
int sum = 0;
go(z, c)sum += d[y][z] + 1 == d[x][z];
cmx(mx, sum);
}
if(mx < mn)mn = mx, u = x;
}
assert(~u);
int p = nav(u - 1);
if(-1 == p)return u - 1;
int x = o[p].fi, y = o[p].se;
if(d[u][x] > d[u][y])swap(x, y);
vector<int>res;
go(x, c)if(d[u][y] + d[y][x] == d[u][x])res.pb(x);
c = res; return calc();
}
int findPrime() {
//rp(i, n){rp(j, n)printf("%d ", d[i][j]); el;}
c.clear();
rp(i, n)c.pb(i);
return calc();
}
标签:rp,int,题解,pb,Nav,go,return,FARIO2019,mx 来源: https://www.cnblogs.com/7KByte/p/16561378.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。