计蒜客——排涝(基础最大流入门)
- 1000ms
- 65536K
到了雨季农业生产的排涝就成了一个大问题。为了保证植物生长的顺利,某县政府决定投资为农田区建立一些排涝渠,将农田里多余的水排到小溪里。
输入第1行包括用一个空格分隔的两个整数N和M,N表示县政府专家设计的排涝渠的数量,M是排涝渠交叉点的数量。其中第一个交点是农田区,交点M是小溪(0≤N≤200,2≤M≤200)。第2行-第N+1行中每行有三个用空格分隔的整数,Si、Ei和Ci。Si和Ei说明了排涝渠的端点,多余的水自Si流向Ei;Ci是这个第i条排涝渠的最大排水量。(1≤Si,Ei≤M,0≤Ci≤10000000)
输出只有一个,为规划好的排涝渠的最大流量。
样例输入
5 4 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10
样例输出
50题解:
基础最大流入门题,这里我用的是Dinic算法。
代码:
#include <algorithm>
#include <vector>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 205;
struct Edge
{
int to,value,rev;//rev用于存储反向边在E[to]中的下标。
Edge() {}
Edge(int a,int b,int c):to(a),value(b),rev(c) {}
};
vector<Edge> E[MAXN];
int deep[MAXN];
int iter[MAXN];//当前边优化
inline void Add(int from,int to,int value)//邻接表加入边
{
E[from].push_back(Edge(to,value,E[to].size()));
E[to].push_back(Edge(from,0,E[from].size()-1));
}
bool BFS(int root,int target)//广搜分层
{
memset(deep,-1,sizeof deep);
queue<int> Q;
deep[root] = 0;
Q.push(root);
while(!Q.empty())
{
int t = Q.front();
Q.pop();
for(int i=0 ; i<E[t].size() ; i++)
{
if(E[t][i].value > 0 && deep[E[t][i].to] == -1)
{
deep[E[t][i].to] = deep[t] + 1;
Q.push(E[t][i].to);
}
}
}
return deep[target] != -1;
}
int DFS(int root,int target,int flow)//深搜寻找增广路径
{
if(root == target)return flow;
for(int &i=iter[root] ; i<E[root].size() ; i++)
{
if(E[root][i].value>0 && deep[E[root][i].to] == deep[root]+1)
{
int nowflow = DFS(E[root][i].to,target,min(flow,E[root][i].value));
if(nowflow > 0)
{
E[root][i].value -= nowflow;
E[E[root][i].to][E[root][i].rev].value += nowflow;
return nowflow;
}
}
}
return 0;
}
int Dinic(int root,int target)
{
int sumflow = 0;
while(BFS(root,target))
{
memset(iter,0,sizeof iter);
int mid;
while((mid=DFS(root,target,INF)) > 0)
{
sumflow += mid;
}
}
return sumflow;
}
int main()
{
int N,M;
int s,e,c;
while(scanf("%d %d",&N,&M)!=EOF)
{
for(int i=0 ; i<N ; i++)
{
scanf("%d %d %d",&s,&e,&c);
Add(s,e,c);
}
printf("%d\n",Dinic(1,M));
}
return 0;
}