hdu 1532最大流 增广路

来源:互联网 发布:php源码怎么安装教程 编辑:程序博客网 时间:2024/05/15 04:33
#include<stdio.h>#include<string.h>#include<queue>#include<algorithm>using namespace std;#define max 210int flow[max][max];int pre[max],mark[max];int n,m,f;int q,z;void maxliu(){    while(1)    {        int i,j;        memset(mark,0,sizeof(mark));        memset(pre,0,sizeof(pre));        queue<int>Q;        mark[1]=1;        Q.push(1);        while(!Q.empty())            {            int cnt=Q.front();            Q.pop();            if(cnt==n)  //如果cnt等于n,说明可以从1到n            break;            for(i=1;i<=n;i++)            {                if(!mark[i] && flow[cnt][i]) //如果没走过这个点,那么就判断,如果可以走,就走                {                    mark[i]=1;                    Q.push(i);   //入队                    pre[i]=cnt;  //这个线段的起点是cnt ,标记起点                }            }        }        if(!mark[n])   //如果mark[n]是0的话,那么说明到不了n        break;        int minx=0x3f3f3f;        for(i=n;i!=1;i=pre[i])        {            minx=min(minx,flow[pre[i]][i]);  //在已经找到的连通的边中找到最短的,说明一次最多可以流这么多的流量        }        for(i=n;i!=1;i=pre[i])        {            flow[pre[i]][i]-=minx;      //正向路:找到最小的之后,进行这个线路的更新,所以减去maxn,如果结果等于0,就说明下条路就不通了            flow[i][pre[i]]+=minx;      //对于反向路来说,存储这个线段可以走的最多的流量        }        f+=minx;                     //找到一点,加一点    }}int main(){         while(scanf("%d%d",&m,&n)!=EOF)     {             memset(flow,0,sizeof(flow));         int end; //不能定义为全局变量         int i;        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&q,&z,&end);            flow[q][z]+=end;  //因为有重边的情况,所以要+=        }        f=0;        maxliu();        printf("%d\n",f);     }     return 0;}


总结一下,最大流,学的时候不好理解,学会了真的很好用




下面是最大流的dinic算法:

#include<stdio.h>#include<string.h>#include<queue>using namespace std;#define max 300#define inf 0x3f3f3f3fint g[max][max];int dist[max];int n,m;int BFS(){    memset(dist,-1,sizeof(dist));    queue<int >Q;    dist[1]=0;    Q.push(1);    while(!Q.empty())    {        int v=Q.front();        Q.pop();        for(int u=1;u<=n;u++)        {            if(g[v][u] && dist[u]<0) //加上dist[u]<0这个条件后,然后就可以专心走一条路了            {                dist[u]=dist[v]+1;  //层次是多少                Q.push(u);            }        }    }    if(dist[n]>0)  //大于0,说明可以到达    return 1;    else    return 0;}int DFS(int x,int low){        int f=0;    if(x==n)    return low;    int i;    for(i=1;i<=n;i++)    {        if(g[x][i] && dist[i]==dist[x]+1)        {            f=DFS(i,min(low,g[x][i]));  //找到最小的那个边            if(f>0)            {                g[x][i]-=f;   //正向减                g[i][x]+=f;   //反向加                return f;            }        }    }    return 0;}int main(){    while(scanf("%d%d",&m,&n)!=EOF)    {        memset(g,0,sizeof(g));        int i,j,x,y,z;        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&x,&y,&z);            g[x][y]+=z;        }    int f=0,t;    while(BFS())   //判断层次    {        while(t=DFS(1,inf))  //一条道走到黑        {            f+=t; //加上没条道的流量        }    }    printf("%d\n",f);         }    return 0;}




0 0