\(USACO\) 上 \(CHAPTER 2\)
的题
黄题难度 但我写了一个网络流
看了下题解 只有我是写的网络流
其他好像都是搜索
思想
网络流中进行是否可以増广和増广是
即(我写的\(dinic\))DINIC中的\(BFS\)和\(DFS\)
判断是否可以走的时候 改成
if(depth[v = edge[e].v] == -1&&(edge[e].w&&able[tp]))//BFS if(depth[v = edge[e].v] == depth[x] + 1&&(edge[e].w&&able[x]))//DFS
就行了 还有一些要注意的点 各位神仙写的时候很容易想到
对了 我用了\(set\)优化
可去重 可排序 为什么不用呢?
时间复杂度
\(O(min(N^{0.67},M^{0.5}) * M*N^2)\)
时间复杂度不比搜索优秀 但练练网络流也挺好的
#include <set> #include <queue> #include <cstdio> #include <vector> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define reg register int #define isdigit(x) ('0' <= x&&x <= '9') template<typename T> inline T Read(T Type) { T x = 0,f = 1; char a = getchar(); while(!isdigit(a)) {if(a == '-') f = -1;a = getchar();} while(isdigit(a)) {x = (x << 1) + (x << 3) + (a ^ '0');a = getchar();} return x * f; } const int MAXN = 10000; int n,cnt,ori_[MAXN]; struct node { int v,w,_nxt; }edge[MAXN],pos_[MAXN]; inline void addedge(int u,int v,int w) { edge[++cnt].v = v; edge[cnt]._nxt = ori_[u]; edge[cnt].w = w; ori_[u] = cnt; } inline void add(int u,int v,int w) {addedge(u,v,w),addedge(v,u,0);} set<int> pany; bool able[MAXN],pr[MAXN]; namespace Dinitz { const int inf = 0x7f7f7f7f; int depth[MAXN],fire[MAXN]; inline bool Bfs(int s,int t) { memset(depth,-1,sizeof(depth)); queue<int> q; q.push(s),depth[s] = 0; while(!q.empty()) { int v,tp = q.front();q.pop(); for(reg e = ori_[tp];e;e = edge[e]._nxt) if(depth[v = edge[e].v] == -1&&(edge[e].w&&able[tp])) { depth[v] = depth[tp] + 1,q.push(v); if(edge[e].w >= 50) able[v] = 1; } } return (depth[t] != -1); } inline int dfs(int x,int t,int _flow) { if(x == t) return _flow; int v,flow_ = 0; for(reg e = fire[x];e;e = edge[e]._nxt) { fire[x] = e; if(depth[v = edge[e].v] == depth[x] + 1&&(edge[e].w&&able[x])) { if(edge[e].w >= 50) able[v] = 1; int flow = dfs(v,t,min(_flow,edge[e].w)); _flow -= flow,flow_ += flow; edge[e].w -= flow,edge[e ^ 1].w += flow; if(!_flow) break; } } if(!flow_) depth[x] = -1; return flow_; } inline int Dinic(int s,int t) { int ans = 0; while(Bfs(s,t)) { for(set<int>::iterator i = pany.begin();i != pany.end();i++) fire[*i] = ori_[*i]; ans += dfs(s,t,inf); } return ans; } } int main() { cnt = 1,n = Read(1); for(reg i = 1;i <= n;i++) { int u = Read(1),v = Read(1),w = Read(1); add(u,v,w); pany.insert(u),pany.insert(v); } for(reg i = 1;i <= cnt;i++) pos_[i] = edge[i]; for(set<int>::iterator i = pany.begin();i != pany.end();i++) { memset(able,0,sizeof(able)); memset(pr,0,sizeof(pr)); set<int> pr_; able[*i] = 1; int num = 1; while(num) { num = 0; for(set<int>::iterator j = pany.begin();j != pany.end();j++) { if(*i == *j||pr[*j]) continue; int max_ = Dinitz::Dinic(*i,*j); for(reg k = 1;k <= cnt;k++) edge[k] = pos_[k]; if(max_ >= 50) pr_.insert(*j),num++,pr[*j] = able[*j] = 1; } } for(set<int>::iterator j = pr_.begin();j != pr_.end();j++) printf("%d %d\n",*i,*j); } return 0; }