E. Two Houses 思维题 + 交互
E. Two Houses 思维题 + 交互
题目大意:
给你一张有向完全图,注意是完全图,也就是说,任意两个点有一条有向边。
给定每一个点的入度,问你能否找到一对 \((a,b)\) 满足有一条从 \(a\) 到 \(b\) 的路径,也有一条从 \(b\) 到 \(a\) 的路径,如果存在,请输入入度差最大的一对,输出 ! a b,如果不存在输出 ! 0 0
你可以进行询问 :\(?\,\,a\,\,b\) 表示,是否存在一条路径从 \(a\) 到 \(b\)
如果存在,则输出 \(YES\) ,不存在则输出 \(NO\)
你可以进行无数次的询问,直到输出 \(YES\)
题解:
首先它是一个有向完全图,如果 \((a,b)\) 询问为 YES,那么进行分析:
- 对于 \(a\) 来说入度为 \(k_a\) ,说明有 \(k_a\) 个点可以到达 \(a\) ,同时也可以说明 \(a\) 可以到达 \(n - 1 - k_a\) 个点
- 对于 \(b\) 来说入度为 \(k_b\) ,说明有 \(k_b\) 个点可以到达 \(b\) ,同时说明 \(b\) 可以到达 \(n-1-k_b\)
- 现在已知 \(a\) 到 \(b\) 存在一条路径,那么接下来只要判断是否 \(b\) 到 \(a\) 也存在一条路径即可。
- 因为到达 \(a\) 的有 \(k_a\) 个点,\(b\) 到达的有 \(n-1-k_b\) 个点,如果到达 \(a\) 和 \(b\) 到达的点有重合,则说明 \(b\) 可以到达 \(a\)
- 那么只要满足等式 \(k_a + n-1-k_b>n-2\) 即可
- 也就是 \(k_a>k_b-1\) ,也就是 \(k_a>=k_b\)
- 得到这个证明之后就很简单了,直接暴力枚举即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 5e2 + 10;
const int mod = 1e9 + 7;
struct node{
int u,v,d;
}e[maxn*maxn];
int in[maxn];
bool cmp(node a,node b){
return a.d>b.d;
}
char s[maxn];
bool ask(int u,int v){
printf("? %d %d\n",u,v);
fflush(stdout);
scanf("%s",s);
if(s[0]=='Y') return true;
return false;
}
int main(){
int n,now = 0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&in[i]);
for(int i=1;i<=n;i++) {
for (int j = i + 1; j <= n; j++) {
int u = i, v = j;
if (in[u] < in[v]) swap(u, v);
e[++now] = {u, v, in[u] - in[v]};
}
}
sort(e+1,e+1+now,cmp);
for(int i=1;i<=now;i++){
auto u = e[i].u;
auto v = e[i].v;
if(ask(u,v)){
printf("! %d %d\n",u,v);
fflush(stdout);
return 0;
}
}
printf("! 0 0\n");
fflush(stdout);
return 0;
}