zoukankan      html  css  js  c++  java
  • 最大流模板

    EK 算法:

    邻接矩阵保存

    模板题hdu3549
    #include<iostream> 
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<climits>
    using namespace std;

    #define N 16
    int capacity[N][N];//容量
    int flow[N];//残余流量
    int pre[N];//前趋

    int n, m;
    queue<int> Q;

    int BFS(int src, int des) {
    //初始化
    while (!Q.empty()) {
    Q.pop();
    }
    for (int i = 1; i < n + 1; i++) {
    pre[i] = -1;
    }
    pre[src] = 0;
    flow[src] = INT_MAX;//初始化源点的流量为无穷大
    Q.push(src);
    while (!Q.empty()) {
    int index = Q.front();
    Q.pop();
    if (index == des) {//找到了增广路径
    break;
    }
    for (int i = 1; i < n + 1; i++) {
    if (i != src && capacity[index][i] > 0 && pre[i] == -1) {
    pre[i] = index;
    //增广路残容流量
    flow[i] = min(capacity[index][i], flow[index]);
    Q.push(i);
    }
    }
    }//while
    if (pre[des] == -1) {
    return -1; //残留图中不存在增广路径
    } else {
    return flow[des];
    }
    }

    int MaxFlow(int src, int des) {
    int aug = 0;
    int sumflow = 0;
    while ((aug = BFS (src, des)) != -1) {
    int k = des; //利用前驱寻找路径
    while (k != src) {
    int last = pre[k];
    capacity[last][k] -= aug;
    capacity[k][last] += aug;
    k = last;
    }
    sumflow += aug;
    }
    return sumflow;
    }

    int main() {
    int cas, cases = 1;
    scanf("%d", &cas);
    while (cas--) {
    scanf("%d%d", &n, &m);
    memset(capacity, 0, sizeof(capacity));
    memset(flow, 0, sizeof(flow));
    for (int i = 0; i < m; i++) {
    int u, v, w;
    scanf("%d%d%d", &u, &v, &w);
    if (u == v) {//起点终点相同
    continue;
    }
    capacity[u][v] += w;
    }
    printf("Case %d: ", cases++);
    printf("%d\n", MaxFlow(1, n));
    }
    return 0;
    }

    ISAP算法

    邻接表存储:

    模板题hdu1532
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int NV = 210;
    const int NE = 410;
    int n,size,head[NV],dis[NV],gap[NV],pre[NV],cur[NV];
    struct edge
    {
    int v,w,next;
    edge(){}
    edge(int v,int next,int w=0):v(v),next(next),w(w){}
    }E[NE];
    inline void insert(int u,int v,int w)
    {
    E[size]=edge(v,head[u],w);
    head[u]=size++;
    E[size]=edge(u,head[v],0);
    head[v]=size++;
    }
    int ISAP(int src,int des)
    {
    int maxflow=0;
    memset(dis,0,sizeof(dis));
    memset(gap,0,sizeof(gap));
    for(int i=0;i<=n;i++)
    cur[i]=head[i];
    int u=pre[src]=src;
    int aug=-1;
    while(dis[src]<n)
    {
    loop: for(int &i=cur[u];i!=-1;i=E[i].next)
    {
    int v=E[i].v;
    if(E[i].w && dis[u]==dis[v]+1)
    {
    aug=min(aug,E[i].w);
    pre[v]=u;
    u=v;
    if(v==des){
    maxflow+=aug;
    for(u=pre[u];v!=src;v=u,u=pre[u])
    {
    E[cur[u]].w-=aug;
    E[cur[u]^1].w+=aug;
    }
    aug=INT_MAX;
    }
    goto loop;
    }
    }
    int mdis=n;
    for(int i=head[u];i!=-1;i=E[i].next)
    {
    int v=E[i].v;
    if(E[i].w && mdis>dis[v])
    {
    cur[u]=i;
    mdis=dis[v];
    }
    }
    if((--gap[dis[u]])==0)
    break;
    gap[dis[u]=mdis+1]++;
    u=pre[u];
    }
    return maxflow;
    }
    int main()
    {
    int m,u,v,w;
    while(scanf("%d %d",&m,&n)==2)
    {
    memset(head,-1,sizeof(head));
    size=0;
    while(m--)
    {
    scanf("%d %d %d",&u,&v,&w);
    insert(u,v,w);
    }
    printf("%d\n",ISAP(1,n));
    }
    return 0;
    }

    邻接矩阵存储:

    View Code
    此模板来自http://www.icycandy.com/blog/template-of-broaden-the-shortest-path-algorithm/comment-page-1
    #include <iostream>
    #include <queue>
    #define msize 1024 //最大顶点数目
    using namespace std;

    int d[msize]; //标号
    int r[msize][msize]; //残留网络,初始为原图
    int num[msize]; //num[i]表示标号为i的顶点数有多少
    int pre[msize];
    int n,m,s,t; //m个顶点,n条边,从源点s到汇点t

    void ini_d() //BFS计算标号,汇点t标号为0
    {
    int k;
    queue<int>Q;

    memset(d,1,sizeof(d));
    memset(num,0,sizeof(num));

    Q.push(t);
    d[t]=0;
    num[0]=1;
    while (!Q.empty())
    {
    k=Q.front(),Q.pop();
    for (int i=0;i<m;i++)
    {
    if (d[i]>=m&&r[i][k]>0)
    {
    d[i]=d[k]+1;
    Q.push(i);
    num[d[i]]++;
    }
    }
    }
    }

    int findAlowArc(int i) //从i出发寻找允许弧
    {
    int j;
    for (j=0;j<m;j++) if (r[i][j]>0&&d[i]==d[j]+1) return j;

    return -1;
    }

    int reLable(int i) //重新标号
    {
    int mm=INT_MAX;
    for (int j=0;j<m;j++)
    if (r[i][j]>0) mm=min(mm,d[j]+1);

    return mm==INT_MAX?m:mm;
    }

    int maxFlow(int s,int t) //从源点s出发的最大流
    {
    int flow=0,i=s,j;
    int delta; //增量

    memset(pre,-1,sizeof(pre));
    while (d[s]<m)
    {
    j=findAlowArc(i);
    if (j>=0)
    {
    pre[j]=i;
    i=j;
    if (i==t) //更新残留网络
    {
    delta=INT_MAX;
    for (i=t;i!=s;i=pre[i]) delta=min(delta,r[pre[i]][i]);
    for (i=t;i!=s;i=pre[i]) r[pre[i]][i] -= delta, r[i][pre[i]] += delta;
    flow += delta;
    }
    }
    else
    {
    int x=reLable(i); //重新标号
    num[x]++;
    num[d[i]]–;
    if (num[d[i]]==0) return flow; //间隙优化
    d[i]=x;
    if (i!=s) i=pre[i];
    }
    }

    return flow;
    }




  • 相关阅读:
    英语范文——人的名字的重要性
    英语写作常用句型
    英语范文——构建绿色校园
    OpenGL实例:三角形
    Python+Selenium笔记(二):配置谷歌+IE环境
    Python+Selenium笔记(一):环境配置+简单的例子
    Python笔记(八):web开发
    Python笔记(七):字典、类、属性、对象实例、继承
    Python笔记(六):推导数据
    Python笔记(五):异常处理和数据存储
  • 原文地址:https://www.cnblogs.com/nanke/p/2377255.html
Copyright © 2011-2022 走看看