hdu 6582 让最短路变长(难)dijkstra+最大流

题解转自:https://www.cnblogs.com/Chen-Jr/p/11228767.html
题目链接:https://vjudge.net/problem/HDU-6582
题意:给你一张有向图,现在你需要删除一些边,每次删除的花费是边的权值,使得最短路增大,现在问你最小的花费。
思路:让最短路变长,应该先把最短路拿出来建图然后用一个最小的花费破坏这个图即可。首先以1号节点跑dijkstra,然后以n号节点跑dijkstra。遍历每一条边,如果dist[xx[i]]+c[i]+dist1[yy[i]]==dist[n],说明这条边就是最短路上的一条边,然后用dinic跑最大流即可。

#pragma comment(linker,"/STACK":102400000,102400000")
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <utility>
using namespace std;
const int maxn=1e4+5;
long long dist[maxn],dist1[maxn];
const long long inf=1e16;
const int inf1=1e9+5;
vector <pair<int,int> >g[maxn];
bool done[maxn];
int xx[maxn],yy[maxn],c[maxn];
struct heapnode
{
    long long d;
    int u;
    bool operator <(const heapnode &s) const
    {
        return d>s.d;
    }
};
int n,m;
priority_queue <heapnode> q;
void dijkstra(int s,long long *d)
{
    memset(done,0,sizeof(done));
    for(int i=1;i<=n;i++)
    {
        d[i]=inf;
    }
    q.push(heapnode{0,s});
    d[s]=0;
    while(!q.empty())
    {
        heapnode x=q.top();
        q.pop();
        int u=x.u;
        if(done[u])
            continue;
        done[u]=true;
        for(int i=0;i<g[u].size();i++)
        {
            int to=g[u][i].first;
            int w=g[u][i].second;
            if(d[to]>d[u]+w)
            {
                d[to]=d[u]+w;
                q.push(heapnode{d[to],to});
            }
        }
    }
    return ;
}
struct edge
{
    int to,cap,rec;
};
vector <edge> gg[maxn];
int level[maxn];
int iter[maxn];
void add(int from,int to,int cap)
{
    gg[from].push_back((edge){to,cap,gg[to].size()});
    gg[to].push_back((edge){from,0,gg[from].size()-1});
}
void bfs(int s)
{
    memset(level,-1,sizeof(level));
    queue<int> q;
    q.push(s);
    level[s]=1;
    while(!q.empty())
    {
        int v=q.front();
        q.pop();
        for(int i=0;i<gg[v].size();i++)
        {
            edge &e=gg[v][i];
            if(e.cap>0&&level[e.to]<0)
            {
                level[e.to]=level[v]+1;
                q.push(e.to);
            }
        }
    }
}
int dfs(int v,int t,int f)
{
    if(v==t)
    {
        return f;
    }
    for(int &i=iter[v];i<gg[v].size();i++)
    {
        edge &e=gg[v][i];
        if(e.cap>0&&level[v]<level[e.to])
        {
            int d=dfs(e.to,t,min(e.cap,f));
            if(d>0)
            {
                e.cap-=d;
                gg[e.to][e.rec].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
int maxflow(int s,int t)
{
    int flow=0;
    while(1)
    {
        bfs(s);
        if(level[t]<0)
        {
            return flow;}
        memset(iter,0,sizeof(iter));
        int f;
        while((f=dfs(s,t,inf1))>0)
        {
            flow+=f;
        }

    }
}

int main()
{int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&xx[i],&yy[i],&c[i]);
            g[xx[i]].push_back(make_pair(yy[i],c[i]));
        }
        dijkstra(1,dist);
        for(int i=1;i<=n;i++)
        {
            g[i].clear();
        }
        for(int i=0;i<m;i++)
        {
            g[yy[i]].push_back(make_pair(xx[i],c[i]));
        }
        dijkstra(n,dist1);
        for(int i=0;i<m;i++)
        {
            if(dist[xx[i]]+c[i]+dist1[yy[i]]==dist[n])
            {
                add(xx[i],yy[i],c[i]);
            }
        }
        printf("%d\n",maxflow(1,n));
        for(int i=1;i<=n;i++)
        {
            g[i].clear();
            gg[i].clear();
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值