链接: A - 美丽的路径
题意:
思路:
- 我们可以二分这个美丽值 , 对于大于等于美丽值的值权值设置为 1,否则为 0 .
- 如果在 联通块中 某条边两端的点权值都是 1 ,那么这个美丽值一定是合法的(我们可以在这条边反复走 无数次,最后的中位数一定会是两端点中的一个且会大于美丽值)。
- 如果不存在这样的相邻的 1 ,那我们就要找到一条路径 1的个数比 0 多,因为已经不存在相邻的 1 了,那唯一合法的解一定是 101010 …1 s 和 t 都是 1,中间部分 01 交替。至于其他情况都是不合法的。
- 怎么找找这条合法路径 , 我们可以先以 s 为起点 跑一次 dfs 把权值为 1 或者 上一个节点权值为 1 的节点标记为可以走 , 再跑一次 dfs (只走可以走的点),如果可以到达 t ,且 s 和 t 权值都为 1 ,那就说明可行。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ioss ios::sync_with_stdio(false);cout.tie(NULL)
const int maxn=1e6 + 7;
const int mod = 998244353;
const int rr = 233;
int T,n,m,s,t;
int num,head[maxn],flag,ma;
int val[maxn],vis[maxn],a[maxn],b[maxn];
struct node{
int v,next;
}e[maxn << 1];
void add(int u,int v){
e[num].v = v;
e[num].next = head[u];
head[u] = num ++;
}
void dfs1(int u){
for(int i = head[u]; i != -1; i = e[i].next){
int to = e[i].v;
if(a[u] && a[to]) flag = 1; // 两个 1 答案可行
if(a[u] || a[to]) b[to] = 1; // 代表这个点在下一个 dfs 可以走 ,保证是 01 交替
if(vis[to] == 0){
vis[to] = 1;
dfs1(to);
}
}
}
void dfs2(int u){
for(int i = head[u]; i != -1; i = e[i].next){
int to = e[i].v;
if(vis[to] == 0 && b[to]){
vis[to] = 1;
dfs2(to);
}
}
}
int check(int m){
for(int i = 1; i <= n; i ++){
vis[i] = 0;b[i] = 0;
if(val[i] >= m) a[i] = 1;
else a[i] = 0;
}
vis[s] = 1;
flag = 0;
dfs1(s);
if(flag) return 1;
if(a[s] == 0 || a[t] == 0) return 0; // 有一个不为 1 就不行
for(int i = 1; i <= n; i ++){
vis[i] = 0;
}
vis[s] = 1;
dfs2(s);
if(vis[t]) return 1; // 可以到达 可行
return 0;
}
int main (){
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d",&n,&m,&s,&t);
num = 0,ma = 0;
for(int i = 1; i <= n; i ++) head[i] = -1,vis[i] = 0;
for(int i = 1;i <= n; i ++){
scanf("%d",&val[i]);
ma = max(ma,val[i]);
}
for(int i = 1,u,v; i <= m; i ++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
vis[s] = 1;
dfs1(s);
if(vis[t] == 0){ // 判断是否联通
printf ("NO\n");
continue;
}
int l = 1,r = ma,mid,ans = -1;
while(l <= r){
mid = (l + r) / 2;
if(check(mid)){
ans = mid;
l = mid + 1;
}
else r = mid - 1;
}
if(ans == -1) printf ("NO\n");
else {
printf ("YES\n");
printf ("%d\n",ans);
}
}
return 0;
}