2019 Multi-University Training Contest 1 E Path(最短路+最小割)

题意

链接:https://vjudge.net/problem/HDU-6582

给定一个有向图,可以有重边,每条边上有一个权值表示删掉这条边的代价,问最少花费多少代价能使从s到t节点的最短路径增大?1≤n,m≤10000

思路

容易想到应该是删最短路上的边,最短路可能不止一条,所以使原图1到n的所有最短路不连通即可,这就是最小割呀!选出权值和最小的边使得图不连通,这里是使最短路图不连通。

所以做法就是先建两个图,一个是u->v的有向边,另一个是v->u的有向边,从1跑一下Dijkstra,从n跑一下Dijkstra,我们枚举每条边(u,v),如果这条边是最短路上的边,那么应满足dis1[u]+val(u,v)+dis2[v]=dis1[n],即1到u的最短距离+u到v的距离+v到n的最短距离=1到n的最短距离。

最小割=最大流,跑一下Dinic即可啦。

代码

#include
using namespace std;
#define ll long long
#define int ll
const int N=1e6+5;
const ll inf=1e16;

struct node
{
    int p,w;
    node(int a,int b)
    {
        p=a;
        w=b;
    }
    friend bool operator<(node a,node b) //权值小的先出队
    {
        if(a.w!=b.w) return a.w>b.w;
        return a.p>b.p;
    }
};
vector  eg1[N],eg2[N];
int dis1[N],n,dis2[N];
void add1(int u,int v,int w)
{
    eg1[u].push_back(node(v,w));
}
void add2(int u,int v,int w)
{
    eg2[u].push_back(node(v,w));
}
void Dijkstra1(int now)
{
    for(int i=0; i<=n; i++) dis1[i]=inf;
    dis1[now]=0;
    priority_queue  pq;
    pq.push(node(now,dis1[now]));
    while(!pq.empty())
    {
        node f=pq.top();
        pq.pop();
        for(int i=0; it.w+f.w)
            {
                dis1[t.p]=t.w+f.w;
                pq.push(node(t.p,dis1[t.p]));
            }
        }
    }
}
void Dijkstra2(int now)
{
    for(int i=0; i<=n; i++) dis2[i]=inf;
    dis2[now]=0;
    priority_queue  pq;
    pq.push(node(now,dis2[now]));
    while(!pq.empty())
    {
        node f=pq.top();
        pq.pop();
        for(int i=0; it.w+f.w)
            {
                dis2[t.p]=t.w+f.w;
                pq.push(node(t.p,dis2[t.p]));
            }
        }
    }
}
/***************************************/
int x,y,z,maxflow,deep[N];//deep深度
struct Edge
{
    int next,to,dis;
} edge[N];
int num_edge=-1,head[N],cur[N];//cur用于复制head
queue  q;

void add_edge(int from,int to,int dis,bool flag)
{
    edge[++num_edge].next=head[from];
    edge[num_edge].to=to;
    if (flag) edge[num_edge].dis=dis;//反图的边权为 0
    head[from]=num_edge;
}

//bfs用来分层
bool bfs(int s,int t)
{
    memset(deep,0x7f,sizeof(deep));
    while (!q.empty()) q.pop();
    for (int i=1; i<=n; i++) cur[i]=head[i];
    deep[s]=0;
    q.push(s);

    while (!q.empty())
    {
        int now=q.front();
        q.pop();
        for (int i=head[now]; i!=-1; i=edge[i].next)
        {
            if (deep[edge[i].to]>inf && edge[i].dis)//dis在此处用来做标记 是正图还是返图
            {
                deep[edge[i].to]=deep[now]+1;
                q.push(edge[i].to);
            }
        }
    }
    if (deep[t]

你可能感兴趣的:(2019 Multi-University Training Contest 1 E Path(最短路+最小割))