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;
}