POJ 1273 (最大流SAP优化模板)

版权声明:get busy living...or get busy dying https://blog.csdn.net/qq_41444888/article/details/88672208

https://cn.vjudge.net/problem/POJ-1273

sap优化:弧优化,sap优化(最短路思想?)

哎谁能给一份好点的模板啊

(收回说过的话,SAP真香)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 205;
struct node
{
    int to, w, next;
    node(int x = 0, int y = 0, int z = 0) : to(x), w(y), next(z){}
}e[maxn*2];
int n, m;
int u, v, w;
int cnt;
int head[maxn];
int gap[maxn], lev[maxn], cur[maxn], pre[maxn];
void addedge(int u, int v, int w)
{
    e[cnt] = node(v, w, head[u]);
    head[u] = cnt ++;
    e[cnt] = node(u, 0, head[v]);
    head[v] = cnt ++;
}
void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
}
int sap(int s, int t)
{
    int minflow, u, flow = 0, neck, i;
    //neck每次记录瓶颈边,因为瓶颈边流过一次之后必定余量为0,而其余的不是,因此下次从neck开始
    memset(gap, 0, sizeof(gap));
    memset(lev, 0, sizeof(lev));
    memset(pre, -1, sizeof(pre));
    for(int i = 1; i <= n; i ++)
        cur[i] = head[i];
    u = s;
    gap[0] = n;
    while(lev[s] < n)
    {
        if(u == t)
        {
            minflow = inf;
            for(i = s; i != t; i = e[cur[i]].to)
            {
                if(minflow > e[cur[i]].w)
                {
                    neck = i;
                    minflow = e[cur[i]].w;
                }
            }
            for(i = s; i != t; i = e[cur[i]].to)
            {
                e[cur[i]].w -= minflow;
                e[cur[i]^1].w += minflow;
            }
            flow += minflow;
            u = neck;
        }
        for(i = cur[u]; ~i; i = e[i].next)
            if(e[i].w && lev[u] == lev[e[i].to] + 1) break;
        if(i != -1)
        {
            cur[u] = i;
            pre[e[i].to] = u;
            u = e[i].to;
        }
        else
        {
            if(! --gap[lev[u]]) break;
            cur[u] = head[u];
            int newlevel = n;
            for(i = head[u]; ~i; i = e[i].next)
                if(e[i].w) newlevel = min(newlevel, lev[e[i].to]);
            lev[u] = newlevel + 1;
            gap[lev[u]] ++;
            if(u != s) u = pre[u];
        }
    }
    return flow;
}
int main()
{
    while(scanf("%d%d", &m, &n) != EOF)
    {
        init();
        for(int i = 1; i <= m; i ++)
        {
            scanf("%d%d%d", &u, &v, &w);
            addedge(u, v, w);
        }
        printf("%d\n", sap(1, n));
    }
    return 0;
}

不知道对不对的自行优化代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 205;
struct node
{
    int to, w, next;
    node(int x = 0, int y = 0, int z = 0) : to(x), w(y), next(z){}
}e[maxn*2];
int n, m;
int u, v, w;
int cnt;
int head[maxn];
int gap[maxn], lev[maxn], cur[maxn], pre[maxn];
void addedge(int u, int v, int w)
{
    e[cnt] = node(v, w, head[u]);
    head[u] = cnt ++;
    e[cnt] = node(u, 0, head[v]);
    head[v] = cnt ++;
}
void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
}
int sap(int s, int t)
{
    int minflow, u, flow = 0, neck, i;
    //neck每次记录瓶颈边,因为瓶颈边流过一次之后必定余量为0,而其余的不是,因此下次从neck开始
    memset(gap, 0, sizeof(gap));
    memset(lev, 0, sizeof(lev));
    memset(pre, -1, sizeof(pre));
    for(int i = 1; i <= t; i ++)
        cur[i] = head[i];
    u = s;
    gap[0] = t;
    while(lev[s] < t)
    {
        if(u == t)
        {
            minflow = inf;
            for(i = s; i != t; i = e[cur[i]].to)
            {
                if(minflow > e[cur[i]].w)
                {
                    neck = i;
                    minflow = e[cur[i]].w;
                }
            }
            for(i = s; i != t; i = e[cur[i]].to)
            {
                e[cur[i]].w -= minflow;
                e[cur[i]^1].w += minflow;
            }
            flow += minflow;
            u = neck;
        }
        for(i = cur[u]; ~i; i = e[i].next)
            if(e[i].w && lev[u] == lev[e[i].to] + 1) break;
        if(i != -1)
        {
            cur[u] = i;
            pre[e[i].to] = u;
            u = e[i].to;
        }
        else
        {
            if(! --gap[lev[u]]) break;
            cur[u] = head[u];
            int newlevel = t;
            for(i = head[u]; ~i; i = e[i].next)
                if(e[i].w) newlevel = min(newlevel, lev[e[i].to]);
            lev[u] = newlevel + 1;
            gap[lev[u]] ++;
            if(u != s) u = pre[u];
        }
    }
    return flow;
}
int main()
{
    while(scanf("%d%d", &m, &n) != EOF)
    {
        init();
        for(int i = 1; i <= m; i ++)
        {
            scanf("%d%d%d", &u, &v, &w);
            addedge(u, v, w);
        }
        printf("%d\n", sap(1, n));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41444888/article/details/88672208