复习了下网络流,自己手动实现了两种增广路网络流

FF算法,裸的贪心+反向弧

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
struct node{
    int to,cap,rev;//这里流量为整数
    node(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){}
};
//为什么在结构体里面要加入反向边这个属性呢,因为我们用的是邻接表
//虽然你立马知道反向边的起点,,但是你却不知道你在这个起点的链表的位置是多少,我们这里可以记录一下

const int maxn=1005;
const int INF=~(0u)>>1;
vector<node> G[maxn];int s,t;
void add(int u,int v,int cap){
    G[u].push_back(node(v,cap,G[v].size()));//rev的索引必然是G[v].size()-1+1,这次一定会加一的嘛
    G[v].push_back(node(u,0,G[u].size()-1));//它的反向边先被push必然是u的最后一条边
}
bool vis[maxn];
int dfs(int v,int t,int f){
    vis[v]=true;
    if(v==t)  return f;
    int i;
    for(i=0;i<G[v].size();++i){
        node &e=G[v][i];
        if(!vis[e.to]&&e.cap>0){
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
int maxflow(){
    int flow=0;
    for(;;){
        memset(vis,0,sizeof(vis));
        int f=dfs(s,t,INF);
        if(f==0) break;
        flow+=f;
    }
    return flow;
}
int main(){
    freopen("testMaxFlow.txt","r",stdin);
    int n,i,u,v,cap;//读入总边数
    scanf("%d",&n);
    scanf("%d%d",&s,&t);
    for(i=0;i<n;++i){
        scanf("%d%d%d",&u,&v,&cap);
        add(u,v,cap);
    }
    printf("ans:%d\n",maxflow());
    return 0;
}

Dinic算法,level和iter数组的当前弧优化非常巧妙

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
struct node{
    int to,cap,rev;
    node(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){}
};
const int maxn=1005;
vector<node> G[maxn];
int s,t;
void add(int u,int v,int cap){
    G[u].push_back(node(v,cap,G[v].size()));
    G[v].push_back(node(u,0,G[u].size()-1));
}
bool vis[maxn];//这个可以不要,level数组可以起两个作用,记录层数和是否被访问过,类似于dp数组
int level[maxn],iter[maxn];
void bfs(){
    memset(level,-1,sizeof(level));
    queue<int> q;
    q.push(s);int i;level[s]=0;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(i=0;i<G[u].size();++i){
            node& e=G[u][i];
            if(e.cap>0&&level[e.to]<0){
                level[e.to]=level[u]+1;
                q.push(e.to);                
            }
        }
    }
    //需要得到所有顶点的level信息,一方面起vis的作用,另一方面起到转移的作用
    //而且考虑到可能同时存在多个最短增广路
}
int dfs(int v,int t,int f){
    printf("v:%d t:%d f:%d\n",v,t,f);
    if(v==t) return f;
    for(int &i=iter[v];i<G[v].size();++i){
        node &e=G[v][i];
        if(e.cap>0&&level[e.to]>level[v]){
            int d=dfs(e.to,t,min(e.cap,f));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }        
    }
    return 0;//这里忘记return 0了...
}
const int INF=~0u>>1;
int maxflow(){
    int flow=0,f;
    for(;;){
        bfs();
        for(int i=0;i<5;++i){
            printf("i:%d level:%d\n",i,level[i]);
        }
        if(level[t]<0) return flow;
        memset(iter,0,sizeof(iter));
        while((f=dfs(s,t,INF))>0) flow+=f; 
    }
}
int main(){
    freopen("testMaxFlow.txt","r",stdin);
    int n,i,u,v,cap;scanf("%d",&n);
    scanf("%d%d",&s,&t);
    for(i=0;i<n;++i){
        scanf("%d%d%d",&u,&v,&cap);
        add(u,v,cap);
    }
    printf("ans:%d\n",maxflow());
    return 0;
}

 

  

posted @ 2017-03-18 16:42  狡啮之仰  阅读(173)  评论(0编辑  收藏  举报