中位数 二分+最长路

https://acm.ecnu.edu.cn/problem/3681/

3681. 中位数

描述 统计 讨论区

单测试点时限: 10.0 秒

内存限制: 256 MB

“你的地图是一张白纸,所以即使想决定目的地,也不知道路在哪里。”

QQ 小方最近在自学图论。他突然想出了一个有趣的问题:

一张由 n 个点,m 条边构成的有向无环图。每个点有点权 Ai 。QQ 小方想知道所有起点为 1 ,终点为 n 的路径中最大的中位数是多少。

一条路径的中位数指的是:一条路径有 n 个点,将这 n 个点的权值从小到大排序后,排在位置 ⌊n2⌋+1 上的权值。

输入

第 1 行输入两个正整数 n,m (1≤n≤106,1≤m≤106 ),表示结点数量和边的数量。

第 2 行输入 n 个由空格隔开的整数 Ai (0≤Ai≤109 ),表示点权。

接下来 m 行,每行输入两个整数 x,y (1≤x,y≤n ),表示有一条 x 指向 y 的单向边,保证给出的图是联通的,可能存在重边。

输出

输出一行包含一个整数,表示最大的中位数。如果不存在任何一条起点为 1 ,终点为 n 的路径,则输出 −1 。

样例

Input

5 5
1 2 3 4 5
1 2
2 3
3 5
2 4
4 5

Output

4

 二分中位数,将图中>=mid的点的权值赋值为1,<mid赋为-1.如果1到N的最长路>=0,那么这个最大中位数一定大于等于次中位数。

//eoj中位数 
#include <bits/stdc++.h>
#define ll long long int 
#define res register int 
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e6+10;
vector<int> v[maxn];
int val[maxn],N,M,dis[maxn],vall[maxn];
bool vis[maxn];
//struct Node{
//	int num,s;
//	bool operator<(const Node a){
//		return this->s>a.s;
//	}
//};

bool judge(int mid)
{
	for(int i=1;i<=N;i++){
		if(val[i]>=mid) vall[i]=1;
		else vall[i]=-1;
		dis[i]=-inf;
		vis[i]=false;
	} 
	queue<int> q;
	q.push(1);
	dis[1]=vall[1];
	while(!q.empty()){
		int x=q.front();
		q.pop();
		vis[x]=false;
		for(int i=0;i<v[x].size();i++){
			int y=v[x][i];
			if(dis[y]<dis[x]+vall[y]){
				dis[y]=dis[x]+vall[y];
				if(!vis[y]){
					q.push(y);
					vis[y]=true;	
				}
			}
		} 
	}
	if(dis[N]>=0) return true;
	else return false;
}

int main()
{
	int Min=inf,Max=0;
	scanf("%d%d",&N,&M);
	for(int i=1;i<=N;i++){
		scanf("%d",&val[i]); 
	}
	int a,b;
	for(int i=0;i<M;i++){
		scanf("%d%d",&a,&b);
		v[a].push_back(b);
	}
	int ans=-1;
	int l=0,r=1e9;
	while(l<=r){
		int mid=(l+r)>>1;
		//然后求解最长路
		if(judge(mid)){
			l=mid+1;
			ans=mid;
		}else r=mid-1;
	}
	printf("%d",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41755258/article/details/87903532