zoukankan      html  css  js  c++  java
  • 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;
    }
    View Code
  • 相关阅读:
    Go-41-回调
    生产者和消费者模型
    等待和通知
    Java 实现多线程的三种方式
    synchronized(修饰方法和代码块)
    volatile 关键字(修饰变量)
    并发三大特性
    Thread 和 Runnable
    《深入理解 Java 虚拟机》学习 -- Java 内存模型
    《深入理解 Java 虚拟机》学习 -- 类加载机制
  • 原文地址:https://www.cnblogs.com/zhgyki/p/10463444.html
Copyright © 2011-2022 走看看