POJ 2135 Farm Tour 【模板】【最小费用最大流】

以前都是拿邻接矩阵来实现,这道题的数据里有重边,所以不得不用邻接表了。

现学了一下,用的是前向星数据结构。可以把前向星想象成链表,next是指针,再具体点就是上一条边的索引(要知道上一条边指的是什么,看我代码内的注释)。head[u]是以u为起点的所有边的入口

但这么实现还是比较麻烦,感觉用vector会好一些。

还有我虽然函数名字叫dinic,但我实际上并不是,只是懒得改了。(因为dinic是一次找到多条增广路)

以后我贴代码不加行号了

#include<iostream>
#include<queue>
#include<cstring>
#define INF 1e9
#define MAXN 1005
using namespace std;
  
int n,ans;
int dist[1005],pre[1005],head[1005];//head[u]为以u为起点的边的第一边的index,用next来遍历所有以u为起点的边
 
struct edge{
    int v,cost,cap,reverse,next;
}edges[MAXN*MAXN];
 
int cnt; 
void addedge(int u,int v,int cost,int cap){
    edges[cnt].v=v;
    edges[cnt].cost=cost;
    edges[cnt].reverse=cnt+1;
    edges[cnt].cap=cap;
    edges[cnt].next=head[u];//上一个以u为起点的边的索引 
    head[u]=cnt++;//更新以u为起点的边的索引,之前位置上的以u为起点的边可以通过现在记录的边的next找到 
     //反向边 
    edges[cnt].v=u;
    edges[cnt].cost=-cost;
    edges[cnt].reverse=cnt-1;
    edges[cnt].cap=0;
    edges[cnt].next=head[v];
    head[v]=cnt++;
 } 
 
bool spfa(){
    for(int i=0;i<=n+1;i++) dist[i]=INF;
    queue<int> q;
    dist[0]=0; pre[0]=-1;//到达0这个点的上一条边是-1 
    q.push(0);
    while(!q.empty()){
        int u=q.front(); q.pop();
        for(int i=head[u];i!=-1;i=edges[i].next){
            int v = edges[i].v;
            if( edges[i].cap>0 && dist[v]>dist[u]+edges[i].cost ){
                dist[v]=dist[u]+edges[i].cost;
                pre[v]=i;
                q.push(v); 
            }
        }
    }
    if( dist[n+1]==INF ) return false;
 
    return true;
}
 
void dinic(){ 
    
    while( spfa() ){
         //退流等价于从汇点到源点建一条流量为正,代价为负的边 
        int u=n+1,edg=pre[u];
        while(u!=0){
            edges[edg].cap-=1;
            edges[ edges[edg].reverse ].cap +=1;
            u=edges[ edges[edg].reverse ].v;
            edg=pre[u];
        }
        ans+=dist[n+1];
    }
     
} 
 
int main(){
    int m;
    cin>>n>>m;
    memset(head,-1,sizeof(head));
 
    for(int i=1;i<=m;i++){
        int u,v,d; cin>>u>>v>>d;
        addedge(u,v,d,1);
        addedge(v,u,d,1);
    }

    addedge(0,1,0,2);
    addedge(n,n+1,0,2);
     
    dinic();
    cout<<ans; 
    return 0;    
}
原文地址:https://www.cnblogs.com/ZhenghangHu/p/9515955.html