Two Houses
题解
首先,我们可以证明,在一个竞赛图中,若入度较大的点有一条路径能够到入度较小的点,那么入度较小的点也必然有一条路径能够到入度较大的点。
证明如下:
我们令点 i i i的入集为 U i U_{i} Ui,出集为 V i V_{i} Vi,点 x , y x,y x,y有 ∣ U x ∣ ⩽ ∣ U y ∣ |U_{x}|\leqslant|U_{y}| ∣Ux∣⩽∣Uy∣,且 y y y有一条能够到 x x x的路径。
若 y y y没有直接到 x x x的边,那么 x x x肯定有一条直接到 y y y的边,它们间肯定是双联通。
若 y y y有直接到 x x x的边,那么 x ∈ V y , y ∈ U x x\in V_{y},y\in U_{x} x∈Vy,y∈Ux。由于 U x ⋂ V x = ∅ , U x ⋃ V x = I − { x } U_{x}\bigcap V_{x}=\empty,U_{x}\bigcup V_{x}=I-\{x\} Ux⋂Vx=∅,Ux⋃Vx=I−{x},所以 ∣ V x ∣ = n − 1 − ∣ U x ∣ |V_{x}|=n-1-|U_{x}| ∣Vx∣=n−1−∣Ux∣。
由于 ∣ U y ∣ ⩾ ∣ U x ∣ |U_{y}|\geqslant |U_{x}| ∣Uy∣⩾∣Ux∣,且 U y U_{y} Uy不包含 x , y x,y x,y,所以 U y ⋂ V x ≠ ∅ U_{y}\bigcap V_{x}\not=\empty Uy⋂Vx=∅。
所以必然存在一个 x x x能到的点拥有一条到 y y y的边。
所以,如果 y y y有一条能到 x x x的路径,那么 x x x必然能到 y y y。
zengbi
所以,我们只需要把所有的点对找出来,按入度差的大小排序,枚举最大的双联通的点对即可。
时间复杂度 O ( n 2 log n ) O\left(n^2\log\,n\right) O(n2logn)。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200005
#define lowbit(x) (x&-x)
#define reg register
#define mp make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x7f7f7f7f;
const int jzm=233;
const int mo=1e9+7;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
int n,tot;char str[10];
struct ming{int k,id;}s[MAXN];
struct node{int u,v,w;}e[MAXN];
bool cmp(ming x,ming y){return x.k<y.k;}
bool cmp1(node x,node y){return x.w>y.w;}
bool Ask(int u,int v){
printf("? %d %d\n",u,v);fflush(stdout);
scanf("\n%s",str+1);return str[1]=='Y';
}
signed main(){
read(n);for(int i=1;i<=n;i++)read(s[i].k),s[i].id=i;
sort(s+1,s+n+1,cmp);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
e[++tot]=(node){s[j].id,s[i].id,s[j].k-s[i].k};
sort(e+1,e+tot+1,cmp1);
for(int i=1;i<=tot;i++)
if(Ask(e[i].u,e[i].v)){printf("! %d %d\n",e[i].u,e[i].v);return 0;}
puts("! 0 0");
return 0;
}