HDU 5889 最短路加网络流

http://acm.hdu.edu.cn/showproblem.php?pid=5889


题意: 一个无向图,每条边距离为1,从N走到1,的最短路。。然后每个路有个价值,求一下最小割


思路:裸题。。手残BFS总是写错,后来换成SPFA枚举一下就好了。。注意!!!新图建单向边来跑最短路。


代码:

#include <iostream>
#include <vector>
#include <stdio.h>
#include <queue>
#include <cstring>
#include <math.h>
using namespace std;
const int MAXN=1100;
int maze[MAXN][MAXN];
int Zdis[MAXN];
int vis[MAXN];
int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];

const int INF=1e9+7;
struct Edge{
    int v;
    int cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
};
struct T{
    int x,y,z;
    T(int _x=0,int _y=0,int _z=0):x(_x),y(_y),z(_z) {}
};
int tmp[MAXN];
vector<Edge>E[MAXN];
vector<T> Z;
void addedge(int u,int v,int w){
    E[u].push_back(Edge(v,w));
}
void Add(int u,int v,int w){
    Z.push_back(T(u,v,w));
}
int cnt[MAXN];//每个点的入队列次数
int dist[MAXN];
int n,m;
bool SPFA(int start,int n)
{
    memset(vis,false,sizeof(vis));
    for(int i=1; i<=n; i++)dist[i]=INF;
    vis[start]=true;
    dist[start]=0;
    queue<int>que;
    while(!que.empty())que.pop();
    que.push(start);
    memset(cnt,0,sizeof(cnt));
    cnt[start]=1;
    while(!que.empty()){
        int u=que.front();
        que.pop();
        vis[u]=false;
        for(int i=0; i<E[u].size(); i++){
            int v=E[u][i].v;
            if(dist[v]>dist[u]+E[u][i].cost){
                dist[v]=dist[u]+E[u][i].cost;
                if(!vis[v]){
                    vis[v]=true;
                    que.push(v);
                    if(++cnt[v]>n)return false;      //cnt[i]为入队列次数,用来判定是否存在负环回路
                }
            }
        }
    }
    return true;
}

void init(){
    for(int i=0;i<=n;i++) E[i].clear();
    Z.clear();
    memset(maze,0,sizeof(maze));
}

int sap(int start,int end,int nodenum){
    memset(cur,0,sizeof(cur));
    memset(dis,0,sizeof(dis));
    memset(gap,0,sizeof(gap));
    int u=pre[start]=start,maxflow=0,aug=-1;
    gap[0]=nodenum;
    while(dis[start]<nodenum){
        loop:
        for(int v=cur[u]; v<nodenum; v++)
            if(maze[u][v] && dis[u]==dis[v]+1){
                if(aug==-1 || aug>maze[u][v])aug=maze[u][v];
                pre[v]=u;
                u=cur[u]=v;
                if(v==end){
                    maxflow+=aug;
                    for(u=pre[u]; v!=start; v=u,u=pre[u]){
                        maze[u][v]-=aug;
                        maze[v][u]+=aug;
                    }
                    aug=-1;
                }
                goto loop;
            }
        int mindis=nodenum-1;
        for(int v=0; v<nodenum; v++)
            if(maze[u][v]&&mindis>dis[v]){
                cur[u]=v;
                mindis=dis[v];
            }
        if((--gap[dis[u]])==0)break;
        gap[dis[u]=mindis+1]++;
        u=pre[u];
    }
    return maxflow;
}

int main()
{
    int t;
    cin>>t;
    while(t--){
        scanf("%d%d",&n,&m);
        int a,b,c;
        init();
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&a,&b,&c);
            addedge(a,b,1);
            addedge(b,a,1);
            Add(a,b,c);
            Add(b,a,c);
        }
        if(!SPFA(1,n)){
            printf("0
");
            continue;
        }
        for(int i=0;i<=n;i++) tmp[i]=dist[i];
        SPFA(n,n);
        for (int i=0;i<Z.size();i++){
            if (dist[Z[i].x]+tmp[Z[i].y]+1==dist[1]) {
                maze[Z[i].x-1][Z[i].y-1]+=Z[i].z;
            }
        }
        int ans=sap(n-1,0,n);
        printf("%d
",ans);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/zhangxianlong/p/10672542.html