LibreOJ #101.最大流
题目描述
输入格式
输出格式
样例
数据范围与提示
题目注意
结果要用long long 保存,int会爆
AC代码
#include<iostream> #include<queue> #include<algorithm> #include<cstdio> using namespace std; const int maxn = 110; const int inf = 0x7fffffff; struct Edge{ int to, w, next; }; Edge e[5000*2+10]; int depth[maxn]; //顶点的层数 int head[maxn]; //实现链式前向星 int cur[maxn]; //当前弧优化,cur就是记录当前点u循环到了哪一条边 int n, m, s, t; int cnt; //边的编号 void init(){ cnt = 0; //s = 1, t = n; for (int i = 0; i <= n; i++) head[i] = -1; } void add_edge(int u, int v, int w){ //加边 e[cnt].to = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt++; } int bfs(int s,int t){ //分层 queue<int> q; for (int i = 0; i <= n; i++) depth[i] = inf; q.push(s); depth[s] = 0; while (!q.empty()){ int p = q.front(); q.pop(); for (int i = head[p]; ~i; i = e[i].next){ //遍历以p为起始的边 if (e[i].w>0 && depth[p]+1<depth[e[i].to]){ //如果是可行边,并且下一个点的深度和当前点的深度相差大于1 depth[e[i].to] = depth[p] + 1; //更新下一个点的深度 q.push(e[i].to); } } } return depth[t] != inf; } int dfs(int u,int flow){ //多次增广 当前点u和flow为当前流量,一开始假设为inf if (u == t) //如果找到汇点 return flow; for (int& i = cur[u]; ~i; i = e[i].next){ //----------修改部分 if (e[i].w > 0 && depth[u] + 1 == depth[e[i].to]){ int delta = dfs(e[i].to, min(flow,e[i].w)); //向下增广 if (delta > 0){ //增广成功 e[i].w -= delta; e[i ^ 1].w += delta; return delta; //向上传递 } } } return 0; //没有增广路,返回0 } long long dinic(){ //dinic主体 long long res = 0; while (bfs(s,t)){ for (int i = 0; i <= n; i++) cur[i] = head[i]; //-------修改部分,注意每次初始化cur while (int delta = dfs(s,inf)) res += 1ll*delta; } return res; } int main() { ios::sync_with_stdio(false); cin >> n >> m>>s>>t; //顶点数和边数 init(); int a, b, c; for (int i = 0; i < m; i++){ cin >> a >> b >> c; add_edge(a, b, c); add_edge(b, a, 0); //注意反向边初始为0 } cout << dinic() << endl; return 0; }
题解效率


浙公网安备 33010602011771号