hdu-4289 最大流Dinic模板题

拆点,套模板。

详情见代码。

//
//  main.cpp
//  hdu_4289
//
//  Created by Luke on 16/8/29.
//  Copyright © 2016年 Luke. All rights reserved.
//
//hdu-4289
#include <iostream>
#include <vector>
#include <queue>
#define N 500 //开两倍大小多一些
#define INF 0x3f3f3f3f
#define LL long long int
using namespace std;
int n,m;//点边
struct Node
{
    int to;
    LL cap;
    unsigned long rev;
};
LL Min(LL a,LL b)
{
    return a>b?b:a;
}
vector<Node> g[N];
int level[N];//用来存放bfs查找最短路的标号
int itor[N];//弧优化
void bfs(LL now)//预先进行广度优先搜索,避免dfs中大量无效查找
{
    fill(level,level+(n<<1)+1,-1);//初始化为-1
    level[now]=0;
    queue<LL> q;
    q.push(now);
    while(!q.empty())
    {
        now=q.front(),q.pop();
        for(int i=0;i<g[now].size();i++)
        {
            Node &e=g[now][i];
            if(e.cap>0&&level[e.to]<0)
                level[e.to]=level[now]+1,q.push(e.to);//迭代标号
        }
    }
}
LL dfs(LL now,LL en,LL f)
{
    if(now==en)
        return f;
    for(int &i=itor[now];i<g[now].size();i++)//弧优化,用&迭代标号,使每次查找边跳过查找过的边
    {
        Node &e=g[now][i];
        if(e.cap>0&&level[e.to]>level[now])//如果level不满足肯定不需要查找
        {
            LL temp=dfs(e.to,en,Min(f,e.cap));
            if(temp>0)
            {
                e.cap-=temp;
                g[e.to][e.rev].cap+=temp;
                return temp;
            }
        }
    }
    return 0;
}
void addEdge(int from,int to,LL cap)
{
    g[from].push_back((Node){to,cap,g[to].size()});
    g[to].push_back((Node){from,0,g[from].size()-1});
}
void ini()
{
    for(int i=0;i<=(n<<1)+1;i++)
        g[i].clear();
    //fill(used,used+n+1,0);
}
LL solve(LL s,LL en)
{
    LL ans=0;
    while(1)
    {
        bfs(s);
        if(level[en]<0)//最短路未查找到路径,返回
            return ans;
        fill(itor,itor+(n<<1)+1,0);
        LL d;
        while((d=dfs(s,en,INF))>0)
            ans+=d;
    }
    return ans;
}
int main(int argc, const char * argv[]) {
    cin.sync_with_stdio(false);
    while(cin>>n>>m)
    {//本题权值在端点处,把点拆分成线段
        ini();
        LL s,e;
        int num,num2;
        cin>>s>>e;
        e+=n;
        for(int i=1;i<=n;i++)
            cin>>num,addEdge(i, i+n, num),addEdge(i+n,i,num);
        for(int i=0;i<m;i++)
            cin>>num>>num2,addEdge(num+n, num2, INF),addEdge(num2+n,num,INF);//这里反向加边时一定要注意始末位置
        cout<<solve(s,e)<<endl;
    }
    return 0;
}

 

posted @ 2016-08-29 15:55  Luke_Ye  阅读(270)  评论(0编辑  收藏  举报