HDU - 5889 Barricade network flow max flow min cut + shortest

Posted by k_ind on Sat, 04 Jan 2020 13:17:42 +0100

Title Link

Meaning: there are n cities with the same length of m roads. The general is located in No. 1 city, and the enemy army is located in No. n city. Now we can know that the army will only follow the shortest path from n to 1. Therefore, the general will decide to place obstacles on these paths (placing obstacles on the corresponding roads will consume corresponding w). It is required that the Army meet obstacles at least once and spend the least.

Idea: since you can only walk the shortest path, run the shortest path first to pick out all the edges you can walk, and then you can find the template problem of the minimum cut.

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define PI acos(-1)
#define INF 0x3f3f3f3f
#define NUM 10100
#define debug true
#define lowbit(x) ((-x)&x)
#define ffor(i,d,u) for(int i=d;i<=u;++i)
#define _ffor(i,u,d) for(int i=u;i>=d;--i)
#define mst(array,Num) memset(array,Num,sizeof(array))
const int p = 1e9+7;
int n,m,maxflow;
int head[NUM/10],d[NUM/10]={},num[NUM/10]={},ednum,dist[NUM/10];
struct edge
{
    int next,to,w;
}e[NUM<<1];
struct Vertex
{
    int id,dis;
    operator>(const Vertex &x)const
    {
        return dis > x.dis ;
    }
};
void read(int &x){
    char ch = getchar();x = 0;
    for (; ch < '0' || ch > '9'; ch = getchar());
    for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}
template <typename T>
void write(T x)
{
    int len=0;char c[21];
    if(x<0)putchar('-'),x*=(-1);
    do{++len;c[len]=(x%10)+'0';}while(x/=10);
    _ffor(i,len,1)putchar(c[i]);
}
inline void bfs()
{
    int x,y;
    ffor(i,1,n)d[i]=INF;
    queue < int > q;
    q.push(n),++num[d[n]=1];
    while(!q.empty())
    {
        x=q.front();q.pop();
        for(int i=head[x];i!=-1;i=e[i].next)
        {
            y=e[i].to;
            if(d[y]!=INF||e[i].w!=0)continue;
            ++num[d[y]=d[x]+1];
            q.push(y);
        }
    }
}
int dfs(int vertex,int minx)
{
    if(!minx||vertex==n)return minx;
    int f,x,flow=0;
    for(int i=head[vertex];i!=-1;i=e[i].next)
    {
        x=e[i].to;
        if(fabs(dist[vertex]-dist[x])==1&&d[vertex]==d[x]+1&&(f=dfs(x,min(minx,e[i].w))))//Calculate only the edge on the shortest path
        {
            minx-=f,flow+=f,e[i].w-=f,e[i^1].w+=f;
            if(!minx)return flow;
        }
    }
    if(!(--num[d[vertex]]))d[1]=n+1;
    ++num[++d[vertex]];
    return flow;
}
inline void ISAP()
{
    bfs();
    while(d[1]<=n)maxflow+=dfs(1,INF);
    write(maxflow);
}
inline void Dij()
{
    priority_queue < Vertex , vector < Vertex > , greater < Vertex > > q;
    Vertex x,y;
    x.id=1,dist[1]=x.dis=0;
    q.push(x);
    while(!q.empty())
    {
        x=q.top(),q.pop();
        if(x.dis>dist[x.id])continue;
        for(int i=head[x.id] ; i!=-1 ; i=e[i].next)
        {
            y.id = e[i].to;
            if(dist[y.id] > dist[x.id] + 1)
            {
                y.dis = dist[y.id] = dist[x.id] + 1;
                q.push(y);
            }
        }
    }
}
inline void AC()
{
    int x,y,wei,t;
    read(t);
    while(t--)
    {
        read(n),read(m);
        maxflow=0,ednum=-1,mst(head,-1),mst(dist,INF);
        ffor(i,1,m)
        {
            read(x),read(y),read(wei);
            e[++ednum].to=y,e[ednum].w=wei,e[ednum].next=head[x],head[x]=ednum;
            e[++ednum].to=x,e[ednum].w=0,e[ednum].next=head[y],head[y]=ednum;
        }
        Dij();
        ffor(i,1,n)
            for(int j = head[i] ; j != -1 ; j = e[j].next)//Reset the forward and reverse edges according to the picked edge
                if(dist[i] > dist[e[j].to])
                    e[j^1].w += e[j].w , e[j].w = 0 ;
        ISAP();
        putchar('\n');
    }
}
int main()
{
    AC();
    return 0;
}