\(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;
}
02-11 10:04