abc 324 f ( 拓扑 + dp + 二分

#include
using namespace std;
using VI = vector;
using ll = long long;
using PII = pair ;
const int mod = 998244353;
int n,m;
int idx = 0;
struct edge{
    int from,next,to;
    double bea , cost , val;
}g[200050];
VI topsort;
int head[200050];
int deg[200050];
double dp[200050];
void add(int u , int v ,double bea , double cost){
    idx++;
    g[idx].bea = bea;
    g[idx].cost = cost;
    g[idx].from = u;
    g[idx].to = v;
    g[idx].next = head[u];
    head[u] = idx;
}

bool check(double mid){
    for(int i = 1 ; i <= idx ; i++){
        g[i].val  = g[i].bea - g[i].cost * mid;
    }
    memset(dp , -2 , sizeof dp);
    dp[1] = 0;
    for(auto x : topsort){
        for(int i = head[x] ; i ; i = g[i].next){
            int to = g[i].to;
            dp[to] = max(dp[to] , dp[x] + g[i].val);
        }
    }
    return dp[n] >= 0;
}


int main(){
    cin>>n>>m;
    for(int i = 1 ; i <= m ; i++){
        int u,v;
        double bea,cost;
        cin>>u>>v>>bea>>cost;
        add(u , v , bea , cost);
        deg[v]++;
    }
    queue q;
    for(int i = 1 ; i <= n ; i++){
        if(deg[i] == 0) q.push(i);
    }
    while(q.size()){
        auto x = q.front();
        q.pop();
        topsort.push_back(x);
        for(int i = head[x] ; i ; i = g[i].next){
            int to = g[i].to;
            deg[to]--;
            if(deg[to] == 0)q.push(to);
        }
    }
    double left = 0 ;
    double right = 1e18;
    while(right - left > 1e-10){
        double mid = (left + right) / 2;
        if(check(mid)) left = mid;
        else right = mid ;
    }
    //cout<

二分一个答案,重新设置边权 bea - mid * cost;

\frac{\sum bea}{\sum cost} >= k

\sum bea - k * \sum cost >= 0 

\sum (bea - cost * k) >= 0

跑拓扑 + dp

你可能感兴趣的:(dp,图,算法,图论,数据结构)