码迷,mamicode.com
首页 > 其他好文 > 详细

网络流 最大流SAPkuangbin模板

时间:2017-10-16 22:18:55      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:scanf   需要   bfs   rom   add   stdin   while   algorithm   总数   

hdu 1532 求1~n的最大流

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;

const int MAXN = 210; //点数的最大值
const int MAXM = 210; //边数的最大值
const int INF = 0x3f3f3f3f;

struct Node
{
        int from, to, next;
        int cap;
} edge[MAXM];
int tol;
int head[MAXN];
int dep[MAXN];
int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y

int n;//n是总的点的个数,包括源点和汇点

void init()
{
        tol = 0;
        memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int w)
{
        edge[tol].from = u;
        edge[tol].to = v;
        edge[tol].cap = w;
        edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].from = v;
        edge[tol].to = u;
        edge[tol].cap = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
}
void BFS(int start, int end)
{
        memset(dep, -1, sizeof(dep));
        memset(gap, 0, sizeof(gap));
        gap[0] = 1;
        int que[MAXN];
        int front, rear;
        front = rear = 0;
        dep[end] = 0;
        que[rear++] = end;
        while (front != rear)
        {
                int u = que[front++];
                if (front == MAXN)
                {
                        front = 0;
                }
                for (int i = head[u]; i != -1; i = edge[i].next)
                {
                        int v = edge[i].to;
                        if (dep[v] != -1)
                        {
                                continue;
                        }
                        que[rear++] = v;
                        if (rear == MAXN)
                        {
                                rear = 0;
                        }
                        dep[v] = dep[u] + 1;
                        ++gap[dep[v]];
                }
        }
}
int SAP(int start, int end)
{
        int res = 0;
        BFS(start, end);
        int cur[MAXN];
        int S[MAXN];
        int top = 0;
        memcpy(cur, head, sizeof(head));
        int u = start;
        int i;
        while (dep[start] < n)
        {
                if (u == end)
                {
                        int temp = INF;
                        int inser;
                        for (i = 0; i < top; i++)
                                if (temp > edge[S[i]].cap)
                                {
                                        temp = edge[S[i]].cap;
                                        inser = i;
                                }
                        for (i = 0; i < top; i++)
                        {
                                edge[S[i]].cap -= temp;
                                edge[S[i] ^ 1].cap += temp;
                        }
                        res += temp;
                        top = inser;
                        u = edge[S[top]].from;
                }
                if (u != end && gap[dep[u] - 1] == 0) //出现断层,无增广路
                {
                        break;
                }
                for (i = cur[u]; i != -1; i = edge[i].next)
                        if (edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1)
                        {
                                break;
                        }
                if (i != -1)
                {
                        cur[u] = i;
                        S[top++] = i;
                        u = edge[i].to;
                }
                else
                {
                        int min = n;
                        for (i = head[u]; i != -1; i = edge[i].next)
                        {
                                if (edge[i].cap == 0)
                                {
                                        continue;
                                }
                                if (min > dep[edge[i].to])
                                {
                                        min = dep[edge[i].to];
                                        cur[u] = i;
                                }
                        }
                        --gap[dep[u]];
                        dep[u] = min + 1;
                        ++gap[dep[u]];
                        if (u != start)
                        {
                                u = edge[S[--top]].from;
                        }
                }
        }
        return res;
}

int main()
{
        // freopen("in.txt","r",stdin);
        //  freopen("out.txt","w",stdout);
        int start, end;
        int m;
        int u, v, z;
        int T;
        while (~scanf("%d%d", &m, &n))
        {
                init();
                while (m--)
                {
                        scanf("%d%d%d", &u, &v, &z);
                        addedge(u, v, z);
                        //addedge(v, u, z);
                }
                //n一定是点的总数,这是使用SAP模板需要注意的
                int ans = SAP(1, n);
                printf("%d\n", ans);
        }
        return 0;
}

hdu 4280  给你岛的坐标求最西边到最东边的最大流

/*
最大流模板
sap
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;

const int MAXN=100010;//点数的最大值
const int MAXM=400010;//边数的最大值
const int INF=0x3f3f3f3f;

struct Node
{
    int from,to,next;
    int cap;
}edge[MAXM];
int tol;
int head[MAXN];
int dep[MAXN];
int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y

int n;//n是总的点的个数,包括源点和汇点

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int w)
{
    edge[tol].from=u;
    edge[tol].to=v;
    edge[tol].cap=w;
    edge[tol].next=head[u];
    head[u]=tol++;
    edge[tol].from=v;
    edge[tol].to=u;
    edge[tol].cap=0;
    edge[tol].next=head[v];
    head[v]=tol++;
}
void BFS(int start,int end)
{
    memset(dep,-1,sizeof(dep));
    memset(gap,0,sizeof(gap));
    gap[0]=1;
    int que[MAXN];
    int front,rear;
    front=rear=0;
    dep[end]=0;
    que[rear++]=end;
    while(front!=rear)
    {
        int u=que[front++];
        if(front==MAXN)front=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dep[v]!=-1)continue;
            que[rear++]=v;
            if(rear==MAXN)rear=0;
            dep[v]=dep[u]+1;
            ++gap[dep[v]];
        }
    }
}
int SAP(int start,int end)
{
    int res=0;
    BFS(start,end);
    int cur[MAXN];
    int S[MAXN];
    int top=0;
    memcpy(cur,head,sizeof(head));
    int u=start;
    int i;
    while(dep[start]<n)
    {
        if(u==end)
        {
            int temp=INF;
            int inser;
            for(i=0;i<top;i++)
               if(temp>edge[S[i]].cap)
               {
                   temp=edge[S[i]].cap;
                   inser=i;
               }
            for(i=0;i<top;i++)
            {
                edge[S[i]].cap-=temp;
                edge[S[i]^1].cap+=temp;
            }
            res+=temp;
            top=inser;
            u=edge[S[top]].from;
        }
        if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路
          break;
        for(i=cur[u];i!=-1;i=edge[i].next)
           if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)
             break;
        if(i!=-1)
        {
            cur[u]=i;
            S[top++]=i;
            u=edge[i].to;
        }
        else
        {
            int min=n;
            for(i=head[u];i!=-1;i=edge[i].next)
            {
                if(edge[i].cap==0)continue;
                if(min>dep[edge[i].to])
                {
                    min=dep[edge[i].to];
                    cur[u]=i;
                }
            }
            --gap[dep[u]];
            dep[u]=min+1;
            ++gap[dep[u]];
            if(u!=start)u=edge[S[--top]].from;
        }
    }
    return res;
}

int main()
{
   // freopen("in.txt","r",stdin);
  //  freopen("out.txt","w",stdout);
    int start,end;
    int m;
    int u,v,z;
    int T;
    scanf("%d",&T);

    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        int minx=10000000;
        int maxx=-10000000;
        int x,y;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            if(minx>x)
            {
                minx=x;
                start=i;
            }
            if(maxx<x)
            {
                maxx=x;
                end=i;
            }
        }


        while(m--)
        {
            scanf("%d%d%d",&u,&v,&z);
            addedge(u,v,z);
            addedge(v,u,z);
        }
        //n一定是点的总数,这是使用SAP模板需要注意的
        int ans=SAP(start,end);
        printf("%d\n",ans);
    }
    return 0;
}

 

网络流 最大流SAPkuangbin模板

标签:scanf   需要   bfs   rom   add   stdin   while   algorithm   总数   

原文地址:http://www.cnblogs.com/Aragaki/p/7678412.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!