- 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; }