二次联通门 : LibreOJ #101. 最大流
2017.6.24
本想着去这个OJ刷刷板子题
结果被这道最大流给坑了。。。
10^6的网络流。。。。
一开始随手写了个dinic
交上去50
有点懵。。后又加了些奇怪的优化
还是50
把class封装去掉
恩, 变成70了
然后就没有然后了
TLE了一整页
后来知道要加当前弧优化才能过
就先去学。
学完后, 加上后
还是70分过不了。。非常绝望啊。。
2017.6.25
好吧。。
有一句话一直没加。。。
是在Flowing函数里的
if (flow != pos)
deep[now] = -1;
这个才是精髓啊。。
/* LibreOJ #101. 最大流(50) Dinic + 当前弧优化 用class封装了起来 50分 */ #include <cstring> #include <cstdio> #include <queue> #define Max 1000090 #define INF 1e9 void read (int &now) { now = 0; register char word = getchar (); while (word < '0' || word > '9') word = getchar (); while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } } int N, M, S, T; inline int min (int a, int b) { return a < b ? a : b; } class Net_Flow_Type { private : int __to[Max * 10]; int __next[Max * 10]; int __flow[Max * 10]; int Edge_Count; int edge_list[Max]; int deep[Max], Answer; int Queue[Max * 10]; int Head, Tail; int __tech_[Max]; public : Net_Flow_Type () { Edge_Count = 1; Answer = 0; } int Flowing (int now, int flow) { if (flow <= 0 || now == T) return flow; int pos = 0, res; for (int i = __tech_[now]; i; i = __next[i]) { if (deep[__to[i]] != deep[now] + 1 || __flow[i] <= 0) continue; res = Flowing (__to[i], min (flow, __flow[i])); if (res > 0) { flow -= res; pos += res; __flow[i] -= res; __flow[i ^ 1] += res; if (__flow[i]) __tech_[now] = i; if (flow <= 0) return pos; } } return pos; } inline void Add_Edge (int from, int to, int flow) { Edge_Count ++; __to[Edge_Count] = to; __next[Edge_Count] = edge_list[from]; edge_list[from] = Edge_Count; Edge_Count ++; __to[Edge_Count] = from; __next[Edge_Count] = edge_list[to]; edge_list[to] = Edge_Count; __flow[Edge_Count - 1] = flow; __flow[Edge_Count] = 0; } void Insert_edges () { for (int i = 1, from, to, flow; i <= M; i ++) { read (from); read (to); read (flow); this->Add_Edge (from, to, flow); } } bool Bfs (int Start) { memset (deep, -1, sizeof deep); Head = 0, Tail = 1; Queue[Head] = Start; deep[Start] = 0; register int now; while (Head < Tail) { now = Queue[Head]; Head ++; for (int i = edge_list[now]; i; i = __next[i]) if (deep[__to[i]] == -1 && __flow[i]) { deep[__to[i]] = deep[now] + 1; if (__to[i] == T) return true; Queue[Tail ++] = __to[i]; } } return deep[T] != -1; } int Dinic () { while (Bfs (S)) { for (int i = 0; i <= N; i ++) __tech_[i] = edge_list[i]; Answer += Flowing (S, INF); } return Answer; } }; Net_Flow_Type Make; int main (int argc, char *argv[]) { read (N); read (M); read (S); read (T); Make.Insert_edges (); printf ("%d", Make.Dinic ()); return 0; }
/* LibreOJ #101. 最大流(70) Dinic + 当前弧优化 没有封装 70分 */ #include <iostream> #include <cstring> #include <cstdio> #define Max 1000010 #define INF 1e8 using namespace std; void read (int &now) { now = 0; char word = getchar (); while (word < '0' || word > '9') word = getchar (); while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } } inline int min (int a, int b) { return a < b ? a : b; } int __tech_[Max]; struct Edge { int to; int next; int flow; }edge[Max * 20]; int Edge_Count = 1, edge_list[Max]; int deep[Max]; inline void AddEdge (int from, int to, int flow) { Edge_Count++; Edge *now = &edge[Edge_Count]; now->flow = flow; now->to = to; now->next = edge_list[from]; edge_list[from] = Edge_Count; } int N, M, S, T; int Get_Flow (int now, int flow) { if (flow <= 0 || now == T) return flow; int res = 0, pos; for (int i = __tech_[now]; i; i = edge[i].next) { if (deep[edge[i].to] != deep[now] + 1 || edge[i].flow <= 0) continue; pos = Get_Flow (edge[i].to, min (flow, edge[i].flow)); res += pos; flow -= pos; edge[i].flow -= pos; edge[i ^ 1].flow += pos; if (edge[i].flow) __tech_[now] = i; if (flow <= 0) return res; } return res; } int queue[Max * 10]; int Answer; void Bfs () { int Head, Tail; int now; bool flag; while (true) { memset (deep, -1, sizeof deep); Head = 0, Tail = 1; queue[0] = S; deep[S] = 0; flag = false; while (Head < Tail) { now = queue[Head++]; for (int i = edge_list[now]; i; i = edge[i].next) if (deep[edge[i].to] < 0 && edge[i].flow) { deep[edge[i].to] = deep[now] + 1; if (edge[i].to == T) { flag = true; break; } queue[Tail++] = edge[i].to; } if (flag == true) break; } if (deep[T] < 0) break; for (int i = 0; i <= N; i ++) __tech_[i] = edge_list[i]; Answer += Get_Flow (S, INF); } } int main (int argc, char *argv[]) { read (N); read (M); read (S); read (T); int x, y, z; for (int i = 1; i <= M; i++) { read (x); read (y); read (z); AddEdge (x, y, z); AddEdge (y, x, 0); } Bfs (); printf ("%d", Answer); return 0; }
/* 此为std 跑的飞快。。。 不是很懂为什么 明明一样的。。。 */ #include <cstdio> #include <iostream> #include <cstring> #include <vector> using namespace std; const int maxn=1000005; const int INF=0x3f3f3f3f; inline int read (int &now) { now = 0; char word = getchar (); while (word < '0' || word > '9') word = getchar (); while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } } struct edge { int to,rev,cap; edge() {} edge(int t,int r,int c) { to=t; rev=r; cap=c; } }; vector<edge> vec[maxn]; int n,m,s,t,que[maxn],h,tail,level[maxn]; void add_edge(int from,int to,int cap) { vec[from].push_back(edge(to,vec[to].size(),cap)); vec[to].push_back(edge(from,vec[from].size()-1,0)); } bool bfs() { memset(level,-1,sizeof(level)); level[que[h=tail=1]=s]=0; int x,y; while (h<=tail) { x=que[h++]; for (int i=0; i<vec[x].size(); i++) { y=vec[x][i].to; if (vec[x][i].cap==0||level[y]!=-1) continue; level[y]=level[x]+1,que[++tail]=y; } } return level[t]!=-1; } int dfs(int x,int f) { if (x==t) return f; int used=0,w,y; for (int i=0; i<vec[x].size(); i++) { y=vec[x][i].to; if (vec[x][i].cap==0||level[y]!=level[x]+1) continue; w=dfs(y,min(f-used,vec[x][i].cap)); used+=w,vec[x][i].cap-=w,vec[y][vec[x][i].rev].cap+=w; if (used==f) return f; } if (used!=f) level[x]=-1; return used; } int max_flow() { int flow=0; while (bfs()) flow+=dfs(s,INF); return flow; } int main() { read (n); read (m); read (s); read (t); int u, v, c; for (int i=0; i<m; i++) { read (u); read (v); read (c); add_edge(u,v,c); } printf ("%d ",max_flow()); return 0; }
自己的AC代码:
#include <cstring> #include <cstdio> #include <queue> #define Max 1000090 #define INF 1e9 void read (int &now) { now = 0; register char word = getchar (); while (word < '0' || word > '9') word = getchar (); while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } } int N, M, S, T; inline int min (int a, int b) { return a < b ? a : b; } class Net_Flow_Type { private : int __to[Max * 10]; int __next[Max * 10]; int __flow[Max * 10]; int Edge_Count; int edge_list[Max]; int deep[Max], Answer; int Queue[Max * 10]; int Head, Tail; int __tech_[Max]; public : Net_Flow_Type () { Edge_Count = 1; Answer = 0; } int Flowing (int now, int flow) { if (flow <= 0 || now == T) return flow; int pos = 0, res; for (int i = __tech_[now]; i; i = __next[i]) { if (deep[__to[i]] != deep[now] + 1 || __flow[i] <= 0) continue; res = Flowing (__to[i], std :: min (flow, __flow[i])); if (res > 0) { flow -= res; pos += res; __flow[i] -= res; __flow[i ^ 1] += res; if (__flow[i]) __tech_[now] = i; if (flow <= 0) return pos; } } if (pos != flow) deep[now] = -1; return pos; } inline void Add_Edge (int from, int to, int flow) { Edge_Count ++; __to[Edge_Count] = to; __next[Edge_Count] = edge_list[from]; edge_list[from] = Edge_Count; Edge_Count ++; __to[Edge_Count] = from; __next[Edge_Count] = edge_list[to]; edge_list[to] = Edge_Count; __flow[Edge_Count - 1] = flow; __flow[Edge_Count] = 0; } void Insert_edges () { for (int i = 1, from, to, flow; i <= M; i ++) { read (from); read (to); read (flow); this->Add_Edge (from, to, flow); } } bool Bfs (int Start) { for (int i = 0; i <= N; i ++) deep[i] = -1; Head = 0, Tail = 1; Queue[Head] = Start; deep[Start] = 0; register int now; while (Head < Tail) { now = Queue[Head]; Head ++; for (int i = edge_list[now]; i; i = __next[i]) if (deep[__to[i]] == -1 && __flow[i]) { deep[__to[i]] = deep[now] + 1; if (__to[i] == T) return true; Queue[Tail ++] = __to[i]; } } return deep[T] != -1; } int Dinic () { while (Bfs (S)) { for (int i = 0; i <= N; i ++) __tech_[i] = edge_list[i]; Answer += Flowing (S, INF); } return Answer; } }; Net_Flow_Type Make; int main (int argc, char *argv[]) { read (N); read (M); read (S); read (T); Make.Insert_edges (); printf ("%d", Make.Dinic ()); return 0; }