EOJ Monthly 2019.2 E. 中位数 (二分+dfs)
Posted zhgyki
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EOJ Monthly 2019.2 E. 中位数 (二分+dfs)相关的知识,希望对你有一定的参考价值。
题意:
在一个n个点,m条边的有向无环图中,求出所有从1到n
的路径的中位数的最大值
一条路径的中位数指的是:一条路径有 n 个点,
将这 n 个点的权值从小到大排序后,排在位置 ⌊n2⌋+1 上的权值。
思路:
看到权值为1~1e9,可以想到用二分答案,然后我们在验证的时候
可以将小于mid的边权设为-1,大于为1这样遍历一遍序列加起来的值
刚好为0
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define N 1000005 const ll INF=2e9; int n,m; int a[N]; vector<int>v[N]; int dis[N]; int vis[N]; int dfs(int mid,int x) { if(vis[x]) return dis[x]; int tmp=a[x]>=mid?1:-1; vis[x]=1; for(int i=0;i<v[x].size();i++) { int t=v[x][i]; dis[x]=max(dis[x],tmp+dfs(mid,t)); } return dis[x]; } bool check(int mid) { for(int i=1;i<=n;i++) dis[i]=-INF; memset(vis,0,sizeof(vis)); vis[1]=1; dis[1]=a[1]>=mid?1:-1; return dfs(mid,n)>=0; } int main() { while(~scanf("%d %d",&n,&m)) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); while(m--) { int x,y; scanf("%d%d",&x,&y); v[y].push_back(x); } ll l=0,r=INF; ll ans=-1; while(l<=r) { ll mid=l+r>>1; if(check(mid)) { l=mid+1; ans=mid; } else r=mid-1; } printf("%lld ",ans); } return 0; }
以上是关于EOJ Monthly 2019.2 E. 中位数 (二分+dfs)的主要内容,如果未能解决你的问题,请参考以下文章
EOJ Monthly 2019.2 (based on February Selection) D.进制转换
EOJ Monthly 2020.7 Sponsored by TuSimple E.因数串 数学/ 构造
EOJ Monthly 2019.11 E. 数学题(莫比乌斯反演+杜教筛+拉格朗日插值)