题目链接:https://codeforces.com/contest/1779/problem/E
题解:
将一个完全图的每条边定向,构成的有向图叫做 竞赛图
也很好理解,\(n\) 个人两两比赛,肯定有胜有负,赢家向负者连边,就构成了这张图。
竞赛图有一些有用的性质:
- 缩点后拓扑序唯一(也可以简单理解成构成一条链)
- (兰道定理)将所有点的出度 \(s_i\) 升序排列,那么 \(\sum_{i=1}^ks_i \geq \binom{k}{2}\),而且 \(k=n\) 的时候必取等
证明可以考虑 \(1..k\) 的所有人两两比赛(不考虑其余人),必然有胜者 \(i\),也就是 \(s_i\) +1,这一共进行 \(\binom{k}{2}\) 场比赛,因此 \(\sum s_i\) 至少是 \(\binom{k}{2}\)
可以感性理解成最“菜”的 \(k\) 个人自己就能构成一个竞赛图(除去外边人的干扰),求的是出度是因为入度会有其它人的干扰 - 若有环,则必有三元环(证明可以用染色之类的证吧,画几个 \(n=4/5\) 的情况看看就行了)
本题中,可以发现所要求的就是缩点之后拓扑序最小的那个点对应的原图强连通分量里的点
如何找这个强连通分量呢?想到兰道定理
但是兰道定理关注的是最“菜”的,但是现在要求最“强”的。我们可以借助感性理解。把最强的几个点(每次查询除自己外其它所有点得到出度,把出度按从大到小排序)拿出来,去掉其它的点,关注一下这个子图所有点的入度(不要出度是因为会与其它点相关,这和兰道定理的时候正好反过来了),同理如果入度是 \(\binom{k}{2}\) 的形式就说明这是个强连通分量,而且是拓扑序最小的。
代码:
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 2e5+5;
int n;
struct node{int out,id;}de[maxn];
int cmp(node a,node b){return a.out>b.out;}
int check(int in){
in<<=1;
int sq = (int)sqrt(1.0 * in+0.5);
return sq*(sq+1) == in;
}
int res[maxn];
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
printf("? %d ",i);
for(int j=1;j<=n;j++)printf("%d",i!=j);
puts("");fflush(stdout);
scanf("%d",&de[i].out);de[i].id = i;
}
sort(de+1,de+n+1,cmp);
int ans=n;
int in=0;
for(int i=1;i<=n;i++){
in += (n-1) - de[i].out;
int rst = i;
if(in == rst*(rst-1)/2){ans = i;break;}
}
for(int i=1;i<=ans;i++)res[de[i].id] = 1;
printf("! ");for(int i=1;i<=n;i++)printf("%d",res[i]);fflush(stdout);
return 0;
}
标签:兰道,竞赛,int,出度,CF1779E,long,Simultaneous,binom
From: https://www.cnblogs.com/SkyRainWind/p/17068333.html