zoukankan      html  css  js  c++  java
  • 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;    
    }
  • 相关阅读:
    树形数据深度排序处理示例(递归法).sql
    12种JavaScript MVC框架之比较
    逐级汇总示例(用户定义函数法).sql
    名次查询的处理示例.sql
    实现删除指定结点及所有子节点的处理触发器.sql
    memcpy和memmove的区别
    据说是月薪2W的笔试题
    C++重点知识
    Java初学者需掌握的30个概念
    (转)微软面试题
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9515955.html
Copyright © 2011-2022 走看看