Dinic模板题

简介: 快几个月没碰过图论题了, 感觉忘的差不多了,准备从基础开始重新刷一遍水题(菜B一个)

题目链接

http://hihocoder.com/problemset/problem/1369

一道赤裸裸的最大流模板题,直接上代码吧

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>

using namespace std;
#define maxn 10005

int S, T;
int N , M;
struct node
{
    int from ;
    int to;
    int cal;
    int flow;
    node(int a,int b,int c,int d)
    {
        from = a, to = b , cal = c, flow = d;//应该是cap ,见谅- -。
    }

};
vector<int>G[maxn];
vector<node>Edges;

int vis[maxn];
int deep[maxn];
int iter[maxn];

void edg_add(int from,int to,int cal)
{
    Edges.push_back(node(from,to,cal,0));
    Edges.push_back(node(to,from,0,0));
    int size = Edges.size();
    G[to].push_back(size-1);
    G[from].push_back(size-2);
}

int BFS()
{
    memset(vis,0,sizeof(vis));
    deep[S] = 1;

    queue<int>Q;
    Q.push(S);
    vis[S] = 1;
    while( !Q.empty() )
    {
        int u = Q.front();Q.pop();

        for(int i = 0 ; i < G[u].size() ; ++i)
        {
            node &e = Edges[G[u][i]];
            if ( !vis[e.to] && e.cal > e.flow )
            {
                vis[e.to] = 1;
                deep[e.to] = deep[u] + 1;
                Q.push(e.to);
            }
        }
    }
    return vis[T];
}

int DFS(int u,int a)
{
    if(u == T || a == 0)
		return a;
	int f , flow = 0;
	for(int& i = iter[u]; i < (int)G[u].size(); ++i)//防止每次都从0开始
	{
		node & e = Edges[G[u][i]];
		if(deep[e.to] == deep[u] + 1 && (f = DFS(e.to , min(a,e.cal - e.flow))) > 0 )
		{
			e.flow += f;
			Edges[G[u][i]^1].flow -= f;
			flow += f;
			a -= f;
			if( a == 0 )break;
		 }
	}
	return flow;
}

int Dinic()
{
    int res = 0;
    while(BFS())
    {
        memset(iter,0,sizeof(iter));
        res += DFS(1,1e9);
    }
    return res;
}

int main()
{
    cin >> N >> M;
    S = 1 ;T = N;
    for(int i = 0 ;i < M ; ++i)
    {
        int a,b,c;
        cin >> a >> b >> c;
        edg_add(a,b,c);
    }
    cout << Dinic() << endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值