Nowcoder9985A.美丽的路径(二分答案)

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);
	}
}
原文地址:https://www.cnblogs.com/zhanglichen/p/14532745.html