| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 53153 | Accepted: 20238 |
Description
Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network.
Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle.
Input
Output
Sample Input
5 4 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10
Sample Output
50
1、EK
思路:
网络流EK算法入门模板题;
资料 http://blog.sina.com.cn/s/blog_6cf509db0100uy5n.html
代码:
#include <stdio.h>
#include <string.h>
#include <queue>
#define INF 0xfffffff
#define N 220
using namespace std;
int map[N][N];
bool vis[N]; // bfs 时标记,避免走回路
int pre[N]; // 父节点
bool bfs(int start, int num)
{
memset(pre, -1, sizeof(pre)); // 父节点初始化成-1
memset(vis, 0, sizeof(vis));
queue<int>q;
pre[start] = start; // 起点的父节点是本身
vis[start] = 1;
q.push(start);
int cur;
while(!q.empty()){
cur = q.front();
q.pop();
for(int i = 1; i <= num; i ++){
if(map[cur][i] > 0 && !vis[i]){ // 有关系,并且未曾访问
pre[i] = cur;
vis[i] = 1;
if(i == num) // 到达终点
return 1;
q.push(i);
}
}
}
return 0;
}
int EK(int start, int num)
{
int ans = 0, min_w;
while( bfs(start, num) ){
min_w = INF;
for(int i = num; i != start; i = pre[i]){ // 寻找最小边权,(逆向,找父节点)
min_w = min_w < map[pre[i]][i] ? min_w : map[pre[i]][i];
}
for(int i = num; i != start; i = pre[i]){ // 更新边权,建立反向边
map[pre[i]][i] -= min_w;
map[i][pre[i]] += min_w;
}
ans += min_w;
}
return ans;
}
int main()
{
int n, m;
int start, end, p, ans;
while(scanf("%d%d", &m, &n) != EOF){
memset(map, 0, sizeof(map));
for(int i = 0; i < m; i ++){
scanf("%d%d%d", &start, &end, &p);
map[start][end] += p; // 注意,可能有重边
}
ans = EK(1, n);
printf("%d\n", ans);
}
return 0;
}
2、Dinic
思路:
bfs时每一步对原图进行分层,然后用DFS求增广路;
代码:
#include <stdio.h>
#include <string.h>
#include <queue>
#define INF 0x7fffffff
#define N 220
#define min(a, b) a < b ? a : b
using namespace std;
int level[N]; // 用于分层
int map[N][N];
int start, end;
bool bfs()
{
queue<int>q;
q.push(start);
memset(level, 0, sizeof(level));
level[start] = 1;
int cur;
while(!q.empty()){
cur = q.front();
q.pop();
for(int i = 1; i <= end; i ++){
if(!level[i] && map[cur][i] > 0){ // 条件:之前未被分层,并且两点有边权
level[i] = level[cur] + 1;
if(i == end){ // 到达终点
return 1;
}
q.push(i);
}
}
}
return 0;
}
int dfs(int cur, int cp)
{
if(cur == end) // 到达终点
return cp; // 返回值是整条路径最小边权值
int t, tmp = cp;
for(int i = start; i <= end && tmp; i ++){
if(level[i] == level[cur] + 1 && map[cur][i] > 0){ // 条件:两点之间层数相差1,并且两点之间有边权
t = dfs(i, min(tmp, map[cur][i])); // t接收此条路径最小边权值
map[cur][i] -= t; // 更新边权
map[i][cur] += t; // 建立反向边
tmp -= t;
}
}
return cp - tmp;
}
int Dinic()
{
int ans = 0, min_w;
while( bfs() ){ // 判断能否走通
while( (min_w = dfs(start, INF)) ){ // 深搜整条路径
ans += min_w;
}
}
return ans;
}
int main()
{
start = 1;
int ct, x, y, p, ans;
while(scanf("%d%d", &ct, &end) != EOF){
memset(map, 0, sizeof(map));
for(int i = 0; i < ct; i ++){
scanf("%d%d%d", &x, &y, &p);
map[x][y] += p;
}
ans = Dinic();
printf("%d\n", ans);
}
return 0;
}
364



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



