最大流模板(學習中)

1.EK

/*
poj 1273
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
#define ll long long
#define MAXN 205
#define INF 0x3f3f3f3f
int n,m;
int flow[MAXN][MAXN],cap[MAXN][MAXN],a[MAXN],p[MAXN];
//分別爲:flow[u][v]爲<u,v>流量、cap[u][v]爲<u,v>容量、a[i]表示源點s到節點i的路徑上的最小殘留量、p[i]記錄i的前驅
//不用flow也可以,flow+1 就相當於是 cap-1
int Edmonds_Karp(int s,int t)
{
	int i,u,v,sum;
	sum=0;//記錄最大流量
	queue<int>q;//隊列,用bfs找增廣路
	while(1)
	{
		memset(a,0,sizeof(a));//每找一次,初始化一次
		a[s]=INF;
		q.push(s);//源點入隊
		while(!q.empty())
		{
			u=q.front();
			q.pop();
			for(v=1;v<=m;v++)
			{
			    if(!a[v]&&cap[u][v]>0)
				//if(!a[v]&&flow[u][v]<cap[u][v])
				{
					p[v]=u;
					q.push(v);
					a[v]=min(a[u],cap[u][v]);//s-v路徑上的最小殘量
					//a[v]=min(a[u],cap[u][v]-flow[u][v]);//s-v路徑上的最小殘量
				}
			}
		}
		if(a[m]==0)//找不到增廣路,則當前流已經是最大流
			break;
		sum+=a[m];//流加上
		for(i=m;i!=s;i=p[i])// //從匯點順着這條增廣路往回走
		{
		    cap[p[i]][i]-=a[m];//更新正向流量
		    cap[i][p[i]]+=a[m];//更新反向流量
			//flow[p[i]][i]+=a[m];//更新正向流量
			//flow[i][p[i]]-=a[m];//更新反向流量
		}
	}
	return sum;
}
int main()
{
	int v,u,w,i,ans;
    while(~scanf("%d%d",&n,&m))
	{
		//memset(flow,0,sizeof(flow));
		memset(cap,0,sizeof(cap));
		for(i=0;i<n;i++)
		{
			scanf("%d%d%d",&u,&v,&w);
			cap[u][v]+=w;//注意圖中可能出現相同的邊
		}
		ans=Edmonds_Karp(1,m);
		printf("%d\n",ans);
	}
	return 0;
}

2.SAP(鄰接矩陣)----來自kuangbin模板

/*
poj 1149
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
#define ll long long
#define MAXN 105
#define INF 0x3f3f3f3f

int maze[MAXN][MAXN];
int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];

int SAP(int s,int t,int n)
{
    memset(cur,0,sizeof(cur));
    memset(dis,0,sizeof(dis));
    memset(gap,0,sizeof(gap));
    int u=pre[s]=s,maxflow=0,aug=-1;
    gap[0]=n;
    while(dis[s]<n){
loop:
        for(int v=cur[u];v<n;v++)
        {
            if(maze[u][v]&&dis[u]==dis[v]+1)
            {
                if(aug==-1||aug>maze[u][v])
                    aug=maze[u][v];
                pre[v]=u;
                u=cur[u]=v;
                if(v==t)
                {
                    maxflow+=aug;
                    for(u=pre[u];v!=s;v=u,u=pre[u])
                    {
                        maze[u][v]-=aug;
                        maze[v][u]+=aug;
                    }
                    aug=-1;
                }
                goto loop;
            }
        }
            int mindis=n-1;
            for(int v=0;v<n;v++)
            {
                if(maze[u][v]&&mindis>dis[v])
                {
                    cur[u]=v;
                    mindis=dis[v];
                }
            }
            if((--gap[dis[u]])==0)
                break;
            gap[dis[u]=mindis+1]++;
            u=pre[u];
        }

    return maxflow;
}
int main()
{
    int n,m,i,j,s,t,c,u,v,w,ans,gg,x;
    int a[1005],vis[1005];
    while(~scanf("%d%d",&m,&n))
    {
        memset(maze,0,sizeof(maze));
        memset(vis,0,sizeof(vis));
        for(i=1;i<=m;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=1;i<=n;i++)
        {
            scanf("%d",&gg);
            for(j=0;j<gg;j++)
            {
                scanf("%d",&x);
                if(!vis[x])
                {
                    vis[x]=i;
                    maze[0][i]+=a[x];
                }
                else
                {
                    maze[vis[x]][i]=INF;
                }
            }
            scanf("%d",&x);
            maze[i][n+1]=x;
        }
        ans=SAP(0,n+1,n+2);
        printf("%d\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章