题目大意:
就是给出一个DAG, 源点是1, 汇点是M, 给出每条边的容量, 询问1到M的最大流
大致思路:
网络流模板题...
第一次写网络流, 记一下
代码如下:
Result : Accepted Memory : 1576 KB Time : 0 ms
/*
* Author: Gatevin
* Created Time: 2015/12/4 22:08:42
* File Name: Yukinoshita_Yukino.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
/*
* 第一道网络流的题
* 使用Dinic模板
*/
#define maxn 222
//maxn : 点数
#define maxm 222
//maxm : 无向边边数
struct Edge//有向边u->v容量是cap
{
int u, v, nex, cap;
Edge(){}
Edge(int _u, int _v, int _nex, int _cap)
{
u = _u, v = _v, nex = _nex, cap = _cap;
}
};
Edge edge[maxm << 1];
int E;
int head[maxn];
void add_Edge(int u, int v, int c)//第一条边下标必须是偶数
{
edge[++E] = Edge(u, v, head[u], c);
head[u] = E;
edge[++E] = Edge(v, u, head[v], 0);
head[v] = E;
}
int N, M;
int dep[maxn];
bool bfs(int start, int end)
{
int Q[maxn];
int l, r;
l = r = 0;
memset(dep, -1, sizeof(dep));
Q[r++] = start;
dep[start] = 0;
while(l != r)
{
int u = Q[l++];
if(l == maxn) l = 0;
for(int i = head[u]; i + 1; i = edge[i].nex)
{
int v = edge[i].v;
if(edge[i].cap > 0 && dep[v] == -1)
{
dep[v] = dep[u] + 1;
Q[r++] = v;
if(r >= maxn) r = 0;
if(v == end) return 1;
}
}
}
return 0;
}
int dinic(int start, int end)
{
int res = 0;
int top;
int stack[maxn];//stack为存储当前增广路的栈
int cur[maxn];
while(bfs(start, end))//存在增广路就继续增广
{
memcpy(cur, head, sizeof(head));
int u = start;
top = 0;
while(1)
{
if(u == end)//对增广路上的流量做减法并且对反向边容量进行扩张
{
//int min = INF;
int min = 1e9;
int loc;
for(int i = 0; i < top; i++)
if(min > edge[stack[i]].cap)
{
min = edge[stack[i]].cap;
loc = i;
}
for(int i = 0; i < top; i++)
{
edge[stack[i]].cap -= min;
edge[stack[i] ^ 1].cap += min;
}
res += min;
top = loc;
u = edge[stack[top]].u;
}
for(int i = cur[u]; i + 1; cur[u] = i = edge[i].nex)
if(edge[i].cap != 0 && dep[u] + 1 == dep[edge[i].v])//寻找是否有往下一层的路
break;
if(cur[u] != -1)//有下一层的路
{
stack[top++] = cur[u];
u = edge[cur[u]].v;
}
else//不能继续向下走了, 回溯
{
if(top == 0) break;
dep[u] = -1;
u = edge[stack[--top]].u;
}
}
}
return res;
}
int main()
{
while(scanf("%d %d", &N, &M) != EOF)
{
memset(head, -1, sizeof(head));
E = -1;
int u, v, c;
for(int i = 0; i < N; i++)
{
scanf("%d %d %d", &u, &v, &c);
add_Edge(u, v, c);
}
printf("%d\n", dinic(1, M));
}
return 0;
}
本文详细解析了网络流的基本概念,并提供了一个使用Dinic模板解决最大流问题的实例代码,包括如何构建图、BFS寻找增广路径以及Dinic算法的实现细节。
2735

被折叠的 条评论
为什么被折叠?



