BZOJ 4501 旅行

来源:互联网 发布:单片机音乐播放器设计 编辑:程序博客网 时间:2024/06/18 13:13

题目大意 : http://www.lydsy.com/JudgeOnline/problem.php?id=4501


首先对于每一个节点,如果f[u] max , 那么每一个 v 都应取到相应的max,那么我们可以按拓扑序逆序(也就是dfs序的逆序) 先算出来每一个f[v],然后再考虑每一个节点的更新,按题意来说,f[u]=f[v]+1的最大值,由于是分式,我们考虑用01分数规划搞,我们设当前二分出来的值为mid , 则应满足 f[v] + 1 - 边数×mid >0 ,由于有限制条件,即有y边必须有x,就是一个典型的最小割了

#include <bits/stdc++.h>using namespace std;const double eps = 1e-7;const int MAXN = 50005,MAXM = 500005,S = 0,T = 5001,inf = 0x7fffffff;bool vis[MAXN];int n,m,k; double f[MAXN];vector<int>G[MAXN];template<typename _t>inline _t read(){    _t x=0,f=1;    char ch=getchar();    for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f=-f;    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+(ch^48);    return x*f;}struct Max_flow{    int first[MAXN],e,d[MAXN],Q[MAXN];    Max_flow(){clear();}    struct edge{        int u,v,next,id;double w;    }a[MAXM];    inline void clear(){        memset(first,0,sizeof first); e = 2;    }    inline void add(int u,int v,int w){        a[e].u = u;a[e].v = v;a[e].id = w;        a[e].next = first[u];first[u] = e++;    }    inline void add(int u,int v,double w){        a[e].u = u;a[e].v = v;a[e].w = w;        a[e].next = first[u];first[u] = e++;    }    inline void push(int u,int v,double w){        add(u,v,w);add(v,u,0.0);    }    inline bool bfs(){        memset(d,-1,sizeof d); d[S] = 0;        int l = 0,r = 1;Q[l] = S;        while(l<r) {            int u = Q[l++];            for(int i = first[u];i;i=a[i].next)                 if(d[a[i].v] == -1 && a[i].w) d[a[i].v] = d[u] + 1,Q[r++] = a[i].v;        }        return d[T] != -1;    }    inline double dfs(int u,double cap) {        if(u == T || cap == 0) return cap;        double Ans = 0.0;        for(int i = first[u];i;i=a[i].next) {            register int v = a[i].v; double w = a[i].w;            if(d[v] == d[u] + 1 && w) {                w = dfs(v,min(w,cap - Ans));                Ans += w;                a[i].w -= w;                a[i^1].w += w;                if(Ans == cap) return Ans;            }        }        if(Ans == 0) d[u] = -1;        return Ans;    }    inline double dinic(){        double Ans = 0.0;        while(bfs()) Ans += dfs(S,inf);        return Ans;    }    inline void build_limit(int u){        int sz = G[u].size();        for(int i = 0;i<sz;i++) push(u,G[u][i],inf);     }    inline void __dfs__(int);}QAQ,QWQ;inline void Max_flow::__dfs__(int u){    if(vis[u]) return; vis[u] = 1;    double l = 0.0,r = 0.0,Ans,mid;    for(int i = first[u];i;i=a[i].next) {        __dfs__(a[i].v);        r = max(r,f[a[i].v] + 1.0);    }    while(l+1e-7<r) {        Ans = 0.0; mid = (l + r)/2.0; QWQ.clear();        for(int i = first[u];i;i=a[i].next) {            register int v = a[i].v; QWQ.build_limit(a[i].id);            if(f[v] + 1 < mid)  QWQ.push(S,a[i].id,mid - f[v] - 1);            else QWQ.push(a[i].id,T,f[v] + 1 - mid),Ans += f[v] + 1 - mid;        }        if(Ans > QWQ.dinic()) f[u] = mid , l = mid;        else r = mid;    }    // f[u] = max(f[v] + 1 / num > L)    // --> f[v] + 1 - num * L > 0;    // --> sigema(f[v] + 1 - num) > 0;}int main(){    n = read<int>();m = read<int>(); k = read<int>();    for(int i = 1;i<=m;i++) {        register int u = read<int>(),v = read<int>();        QAQ.add(u,v,i);     }    for(int i = 1;i<=k;i++) {        register int u = read<int>(),v = read<int>();        G[v].push_back(u);    }    QAQ.__dfs__(1);    printf("%lf\n",f[1]);    return 0;}
原创粉丝点击