A.美丽的路径
题意:
给出一个n*m的无向图,每个点有点权。
定义一条路径的美丽值是这条路径上第[k/2+1]小的点权。
询问是否存在从起点s到终点t的路径,如果存在则输出YES,再输出所有路径的最大美丽值。
如果不存在输出NO。
题解:
考虑二分答案。
假设当前二分的值是k。把所有比k大的点设为1点,把所有比k小的点设为0点。
当两个1点相邻的时候,可以通过在这两个点之间来回走,达到提升美丽值的效果,这种情况直接return 1。
不存在两个1点相邻的时候,查看起点到终点是否存在1010101...或010101..,即01必须交错,因为没有两个1相邻了,如果存在001..必然会导致1的数量不够,美丽值达不到要求。
这一步大力DFS一下就行了。
// Problem: 美丽的路径
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/9985/A
// Memory Limit: 524288 MB
// Time Limit: 6000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//s到t有路径
//考虑二分答案
//大于等于k的点设为1
//小于k的点设为0
//当有两个1的点之间有边的时候,直接return 1
//否则从起点出发,0101010..或者101010..因为没有两个1相连
//所以必须01交错
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int n,m,s,t,_,a[maxn];
vector<int> g[maxn];
int vis[maxn];
int f;
void dfs (int x) {
vis[x]=1;
for (int y:g[x]) {
if (vis[y]) continue;
dfs(y);
}
}
void dfs1 (int x,int k) {
vis[x]=1;
for (int y:g[x]) {
if (a[x]>=k&&a[y]>=k) f=1;
if (vis[y]) continue;
dfs1(y,k);
}
}
void dfs2 (int x,int k,int ff) {
vis[x]=1;
for (int y:g[x]) {
if (vis[y]) continue;
if ((a[y]>=k)^ff) dfs2(y,k,!ff);
}
}
int check (int k) {
for (int i=1;i<=n;i++) vis[i]=0;f=0;
dfs1(s,k);
if (f==1) return 1;
for (int i=1;i<=n;i++) vis[i]=0;
dfs2(s,k,a[s]>=k);
if (vis[t]) return 1;
return 0;
}
int main () {
scanf("%d",&_);
while (_--) {
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1;i<=n;i++) scanf("%d",a+i);
for (int i=1;i<=n;i++) g[i].clear();
for (int i=1;i<=m;i++) {
int x,y;
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
for (int i=1;i<=n;i++) {
vis[i]=0;
}
dfs(s);
if (!vis[t]) {
printf("NO
");
continue;
}
int l=1,r=1e9;
int ans=0;
while (l<=r) {
int mid=(l+r)>>1;
if (check(mid)) {
l=mid+1;
ans=mid;
}
else {
r=mid-1;
}
}
printf("YES
%d
",ans);
}
}