sgu212


HLPP算法:http://xingzheqiang.blog.163.com/blog/static/20561012520127464654159/


时间复杂度: O(n2m) (并不会证明。。。),楼教说对于这种分层图HLPP实际效率更优,不管你信不信,我反正是信了。


#include<cstdio>
#include<cstdlib>
#include<queue>
#include<utility>
#include<iostream>
#include<algorithm>

const int maxn = 1505, maxl = 1505, maxm = 3e5+5, Nya = -1;
const int Ni[2] = {-1,1}, INF = 0x3f3f3f3f;

struct Edge
{
    int v, cap, next;
    Edge(){}
    Edge(int v,int cap,int next):v(v),cap(cap),next(next){}
};

std::priority_queue<std::pair<int,int> > heap; 

int head[maxn], el;
Edge edge[maxm<<1];

int n, m, L, S, T;
int h[maxl], e[maxn];
bool hash[maxn];

void NewEdge(int u,int v,int w)
{
    edge[++el] = Edge(v,w,head[u]), head[u] = el;
}

int HLPP_MaxFlow()
{
    hash[S] = hash[T] = true;

    for(int i = head[S], p; i ; i = edge[i].next)
    {
        e[p = edge[i].v] = edge[i].cap;
        edge[i+Ni[i&1]].cap += edge[i].cap;

        if(!hash[p])
        {
            heap.push(std::make_pair(h[p], p));
            hash[p] = true;
        }
    }

    while(!heap.empty())
    {
        int u = heap.top().second, min = INF;

        heap.pop(), hash[u] = false;

        for(int i = head[u], v; i && e[u]; i = edge[i].next)
        {
            if(h[u] == h[v = edge[i].v] + 1 && edge[i].cap)
            {
                int flow = std::min(edge[i].cap, e[u]);

                e[u] -= flow, edge[i].cap -= flow; 
                e[v] += flow, edge[i+Ni[i&1]].cap += flow;

                if(!hash[v])
                {
                    heap.push(std::make_pair(h[v],v));
                    hash[v] = true;
                }
            }

            if(edge[i].cap) min = std::min(h[v], min); 
        }

        if(e[u])
        {
            h[u] = min + 1;
            heap.push(std::make_pair(h[u], u));
            hash[u] = true; 
        }
    }

}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("sgu212.in","r",stdin);
    freopen("sgu212.out","w",stdout);
#endif

    std::cin >> n >> m >> L;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d",&h[i]);
        if(h[i] == 1) S = i;
        if(h[i] == L) T = i;

        h[i] = L - h[i] + 1;
    }
    for(int i = 1, u, v, w; i <= m; i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        NewEdge(u, v, w), NewEdge(v, u, 0);
    }

    HLPP_MaxFlow();

    for(int i = 1; i <= m; i++)
        printf("%d\n",edge[i<<1].cap);

#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值