HDU 5889 Barricade (最短路+割边)

题意:从1点到n点,有多条路径,在路径上需要放置障碍物,花费最少,使得1->不通,这里的路径都是所有最短的路径

分析:这题本质上是个最小割边问题,直接跑最大流即可,但是这题要求的是最短路径上的最大流,我们可以先从n点预处理一下到每个点的最短距离,然后在增广的时候判断现在的点和下一个点是否满足d[now]=d[next]-1即可,这里由于都是由最短路径向前增广,所以不用考虑负向增广(ltx大佬解释)

代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
#define mem(a,b) memset(a,b,sizeof(a))
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);

using namespace std;

typedef pair<int,int> pii;
const int maxn = 40000 + 7 , inf = 0x3f3f3f3f ;
int nxt[maxn],from[maxn],to[maxn],cap[maxn],head[maxn];
int d[maxn],d2[maxn],prv[maxn],inq[maxn];
int n,m,nEdge;

void addEdge(int u,int v,int c){
    nxt[nEdge]=head[u],from[nEdge]=u,to[nEdge]=v,cap[nEdge]=c,head[u]=nEdge++;
    nxt[nEdge]=head[v],from[nEdge]=v,to[nEdge]=u,cap[nEdge]=0,head[v]=nEdge++;
}
int bfs(int s){
    mem(d2,inf);
    queue<int>q;
    q.push(s);
    d2[s]=0;
    while(!q.empty()){
        int u = q.front();q.pop();

        for(int e = head[u];~e;e=nxt[e]){

            int v = to[e];
            if(d2[v]!=inf)continue;
            d2[v] = d2[u]+1;
            q.push(v);
        }
    }
}

int EK(int s,int t){
    int flow = 0;
    while(1){
        queue<int>q;
        mem(d,0);
        mem(inq,0);
        d[s]=inf;
        q.push(s);
        while(!q.empty()){
            int u = q.front();q.pop();
            inq[u] = 0;
            for(int e = head[u];~e;e=nxt[e]){
                int v = to[e];
                if(cap[e]&&!d[v]&&d2[v]==d2[u]-1){
                    prv[v] = e;
                    d[v] = min(d[u],cap[e]);
                    if(!inq[v]){
                        q.push(v);
                        inq[v] = 1;
                    }
                }
            }
            if(d[t]) break;
        }
        if(!d[t]) break;
        for(int u = t;u!=s;u=from[prv[u]]){
            cap[prv[u]]-=d[t];
            cap[prv[u]^1]+=d[t];
        }
        flow+=d[t];
    }
    return flow;
}

int main(){
   // FRER();
    int T;
    scanf("%d",&T);
    while(T--){
        mem(head,-1);
        nEdge = 0;
        scanf("%d%d",&n,&m);
        while(m--){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            addEdge(a,b,c);
            addEdge(b,a,c);
        }
        bfs(n);
        printf("%d\n",EK(1,n));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Insist_77/article/details/82016698