BZOJ 4501 旅行


题目大意 : 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;
}
基于python实现的粒子群的VRP(车辆配送路径规划)问题建模求解+源码+项目文档+算法解析,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 算法设计的关键在于如何向表现较好的个体学习,标准粒子群算法引入惯性因子w、自我认知因子c1、社会认知因子c2分别作为自身、当代最优解和历史最优解的权重,指导粒子速度和位置的更新,这在求解函数极值问题时比较容易实现,而在VRP问题上,速度位置的更新则难以直接采用加权的方式进行,一个常见的方法是采用基于遗传算法交叉算子的混合型粒子群算法进行求解,这里采用顺序交叉算子,对惯性因子w、自我认知因子c1、社会认知因子c2则以w/(w+c1+c2),c1/(w+c1+c2),c2/(w+c1+c2)的概率接受粒子本身、当前最优解、全局最优解交叉的父代之一(即按概率选择其中一个作为父代,不加权)。 算法设计的关键在于如何向表现较好的个体学习,标准粒子群算法引入惯性因子w、自我认知因子c1、社会认知因子c2分别作为自身、当代最优解和历史最优解的权重,指导粒子速度和位置的更新,这在求解函数极值问题时比较容易实现,而在VRP问题上,速度位置的更新则难以直接采用加权的方式进行,一个常见的方法是采用基于遗传算法交叉算子的混合型粒子群算法进行求解,这里采用顺序交叉算子,对惯性因子w、自我认知因子c1、社会认知因子c2则以w/(w+c1+c2),c1/(w+c1+c2),c2/(w+c1+c2)的概率接受粒子本身、当前最优解、全局最优解交叉的父代之一(即按概率选择其中一个作为父代,不加权)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值