19hdu多校 第一场 Path || bzoj1266 //dijkstra+dinic

题意:给一个有重边的图,删某条边有一个代价wi,求最小的代价和,使得此图的最短路长度边长。

思路:

先处理出最短路相关的图,即保留:d[i.to]=d[now]+d[i.cost]的边。

然后在此图上求最小割(最大流。

因为处理出来的是无环图,所以dinic可以跑的飞快

https://www.lydsy.com/JudgeOnline/problem.php?id=1266

这里用bzoj。

无向图,建图双向判断。

 

/**************************************************************
    Problem: 1266
    User: rshs
    Language: C++
    Result: Accepted
    Time:868 ms
    Memory:24088 kb
****************************************************************/
 
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define LL long long
#define FI first
#define SE second
#define MP make_pair
#define PII pair<int,int>
const int mod = 1e9+7;
const int MX = 2e5+5;
 
LL d[MX];int vis[MX];
 
struct No{LL co,to;};
bool  operator<(const No &x,const No &y){return x.co>y.co;}
vector<No>og[MX];
 
struct no{LL to,cap,rev;}; //arc
vector<no>g[MX]; //图
LL level[MX]; //到起点的距离
LL iter[MX]; //当前弧,在其之前的边已经没用了
void addarc(int s,int e,int c){
    g[s].push_back((no){e,c,g[e].size()});
    g[e].push_back((no){s,0,g[s].size()-1});
}
 
LL aa[MX],bb[MX],cc[MX],dd[MX];
 
//更新层次,即level
void bfs(int s){
    memset(level,-1,sizeof(level));
    level[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=0;i<(int)g[now].size();i++){
            no &arc=g[now][i];
            if(level[arc.to]!=-1||arc.cap<=0) continue;
            level[arc.to]=level[now]+1;
            q.push(arc.to);
        }
    }
}
//寻找增广路
LL dfs(int v,int t,LL f){
    if(v==t) return f;
    for(iter[v];iter[v]<(int)g[v].size();iter[v]++){
        no &arc=g[v][iter[v]];
        if(arc.cap<=0||level[arc.to]!=level[v]+1) continue;
        LL d=dfs(arc.to,t,min(f,arc.cap));
        if(d>0) {
            arc.cap=arc.cap-d;
            g[arc.to][arc.rev].cap+=d;
            return d;
        }
    }
    return 0;
}
LL Dinic(int s,int t){
    LL re=0;
    while(1){
        bfs(s);
        memset(iter,0,sizeof(iter));
        if(level[t]==-1) return re;
        LL f;
        while((f=dfs(s,t,LLONG_MAX))>0)
            re=re+f;
    }
    return re;
}
map<PII,int>ma;
signed main(){
 
        int n,m;cin>>n>>m;ma.clear();
        for(int i=1;i<=n;i++)d[i]=LLONG_MAX/2,vis[i]=0,og[i].clear(),g[i].clear();
        for(int i=1;i<=m;i++){
            cin>>aa[i]>>bb[i]>>cc[i]>>dd[i];
            og[aa[i]].push_back(No{cc[i],bb[i]});
            og[bb[i]].push_back(No{cc[i],aa[i]});
        }
        priority_queue<No>q;d[1]=0;q.push(No{0,1});
        while(!q.empty()){
            int now=q.top().to;q.pop();
            if(vis[now])continue;
            vis[now]=1;
            for(int i=0;i<(int)og[now].size();i++){
                if(og[now][i].co+d[now]<d[og[now][i].to]){
                    d[og[now][i].to]=og[now][i].co+d[now];
                    q.push(No{d[og[now][i].to],og[now][i].to});
                }
            }
        }
        for(int i=1;i<=m;i++){
            if(d[aa[i]]+cc[i]==d[bb[i]])addarc(aa[i],bb[i],dd[i]);
            if(d[bb[i]]+cc[i]==d[aa[i]])addarc(bb[i],aa[i],dd[i]);
        }
        cout<<d[n]<<endl;
        cout<<Dinic(1,n)<<endl;
 
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值