ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Path HDU - 6582【求最短路所有边+最小割】

2020-02-20 21:08:04  阅读:271  来源: 互联网

标签:6582 HDU return dis1 int ll dis2 Path 短路


题意:

  给一个有向图,删除每一条边的代价是边的长度,要求花费最小的代价,使得 1n1\to n1→n最短路变长,求该最小花费。

思路:

  要使得最短路变长,那么删除的边一定要破坏原来的最短路。即要先把所有最短路的所有边找出来,通过删除某几条边,使得所有的最短路无效。
  如何把最短路的所有边全部找出呢?以 dis1[i]dis1[i]dis1[i] 表示原图中,111 号节点到其余节点的最短距离;以 dis2[i]dis2[i]dis2[i] 表示反向建图后 nnn 号节点到各节点的最小距离。如果一条边是最短路径上的边,假设两端点为 uuu 和 vvv,边权为 www,则有:
dis1[u]+w+dis2[v]=dis1[n]dis1[u]+w+dis2[v]=dis1[n]dis1[u]+w+dis2[v]=dis1[n]
所以在正向和反向建图跑两遍最短路后,遍历所有边就可以求出。
接下来在有这些边建成的图上删除边,使得 111 和 nnn 号点不连通。显然就是求最小割。
理论上 DinicDinicDinic 的时间复杂度是 O(n2m)O(n^2*m)O(n2∗m),但实际上要优的多。
AC代码:

#include <bits/stdc++.h>//把所有最短路的所有边找出,然后跑最大流
using namespace std;
typedef long long ll;
typedef pair<ll,int> P;
const int N=1e4+5;
const ll inf=1e16;//注意取值范围设置合理的inf,WA的好惨
struct edge
{
    int from;
    int too;
    ll val;
};
struct node
{
    int to;
    ll val;
    int rev;
};
vector<P>pic[2][N];//正向和反向边
vector<edge>eg;//存边
vector<node>pa[N];//网络流的图
priority_queue<P,vector<P>,greater<P> >que;
queue<int>q;
ll dis[2][N];
int layer[N],iter[N];
int n;
void init()
{
    for(int j=0;j<2;j++)
    {
        for(int i=0;i<=n;i++)
            pic[j][i].clear();
        for(int i=0;i<=n;i++)
            dis[j][i]=inf;
    }
    eg.clear();
    for(int i=0;i<=n;i++)
        pa[i].clear();
}
void dij(int s)
{
    while(!que.empty())
        que.pop();
    if(s==0)
    {
        que.push(make_pair(0,1));
        dis[s][1]=0;
    }
    else
    {
        que.push(make_pair(0,n));
        dis[s][n]=0;
    }
    while(!que.empty())
    {
        P now=que.top();
        que.pop();
        if(now.first>dis[s][now.second])
            continue;
        for(int i=0;i<pic[s][now.second].size();i++)
        {
            P tmp=pic[s][now.second][i];
            if(tmp.first+dis[s][now.second]<dis[s][tmp.second])
            {
                dis[s][tmp.second]=tmp.first+dis[s][now.second];
                que.push(make_pair(dis[s][tmp.second],tmp.second));
            }
        }
    }
}
void addedge(int u,int v,ll w)
{
    pa[u].push_back(node{v,w,pa[v].size()});
    pa[v].push_back(node{u,0,pa[u].size()-1});
}
bool bfs()
{
    while(!q.empty())
        q.pop();
    fill(layer,layer+n+1,-1);
    layer[1]=0;
    q.push(1);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=0;i<pa[now].size();i++)
        {
            node t=pa[now][i];
            if(layer[t.to]<0&&t.val>0)
            {
                layer[t.to]=layer[now]+1;
                q.push(t.to);
                if(t.to==n)
                    return true;
            }
        }
    }
    return false;
}
ll dfs(int v,ll w)
{
    if(v==n)
        return w;
    for(int &i=iter[v];i<pa[v].size();i++)
    {
        node &e=pa[v][i];//cout<<"val="<<e.val<<endl;
        if(e.val>0&&layer[e.to]>layer[v])
        {
            ll d=dfs(e.to,min(w,e.val));
            if(d>0)
            {
                e.val-=d;
                pa[e.to][e.rev].val+=d;
                return d;
            }
        }
    }
    return 0;
}
ll dinic()
{
  ll maxflow=0;
  while(bfs())
  {
      ll f=0;
      fill(iter,iter+1+n,0);
      while((f=dfs(1,inf))>0)
        maxflow+=f;//,cout<<"f="<<f<<endl;
  }
  return maxflow;
}
int main()
{
    int t,m;
    scanf("%d",&t);
    while(t--)
    {
        int u,v;
        ll w;
        scanf("%d%d",&n,&m);
        init();
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%lld",&u,&v,&w);
            pic[0][u].push_back(make_pair(w,v));
            pic[1][v].push_back(make_pair(w,u));
            eg.push_back(edge{u,v,w});
        }
        dij(0);
        dij(1);
        for(int i=0;i<eg.size();i++)
        {
            if(dis[0][eg[i].from]+dis[1][eg[i].too]+eg[i].val==dis[0][n])
                addedge(eg[i].from,eg[i].too,eg[i].val);
        }
        printf("%lld\n",dinic());
    }
    return 0;
}

1024的孤独 发布了121 篇原创文章 · 获赞 11 · 访问量 2112 私信 关注

标签:6582,HDU,return,dis1,int,ll,dis2,Path,短路
来源: https://blog.csdn.net/weixin_43184669/article/details/104417420

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有