复制代码

板子 网络流算法

1 .Edmonds-Karp   算法 : 通过反向增光路+bfs 求解最大流

#include<bits/stdc++.h>
using namespace std;
#define LOACL  freopen("in","r",stdin);\
         freopen("out","w",stdout);
#define FASTIO  ios::sync_with_stdio(false);
#define CLOCK cout<<1.*clock()/CLOCKS_PER_SEC<<"ms"<<"\n";



#define add(u,v,w) e[++tot]=(edge){v,head[u],1},head[u]=tot;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define DBG(x) cout<<(#x)<<"="<<x<<endl
#define DBG2(x,y) cout<<(#x)<<"="<<x<<"\t"<<(#y)<<"="<<y<<endl
#define DBG3(x,y,z) cout<<(#x)<<"="<<x<<"\t"<<(#y)<<"="<<y<<"\t"<<(#z)<<"="<<z<<endl


#define FOR(i, a, b)  for(int i=(a); i<(b); i++)
#define REP(i, a, b)  for(int i=(a); i<=(b); i++)
#define DOWN(i, a, b) for(int i=(a); i>=(b); i--)
#define Loop(i,u) for(int i =head[u];i;i=e[i].nxt)

#define all(x) x.begin(),x.end()
#define low(x) (x)&(-x)
#define pb push_back
typedef long long ll;
typedef double dl;
const int sz = 222;
const int inf = 0x3ffffff;
int m, n, x, y, z, g[sz][sz], pre[sz], flow[sz], maxflow;
queue<int>q ;

 
#if 1
int bfs(int s, int t)
{
    while (!q.empty()) q.pop();
    REP(i, 1, n) pre[i] = -1;
    pre[s] = 0;
    flow[s] = inf;
    q.push(s);
    while (!q.empty())
    {
        int x = q.front() ; q.pop();
        if (x == t)break;
        REP(i, 1, n)
        {
            if (g[x][i] > 0 && pre[i] == -1)
            {
                pre[i] = x;
                flow[i] = min(flow[x], g[x][i]);
                q.push(i);
            }
        }
    }
    if (pre[t] == -1) return -1;
    else return flow[t];

}

#endif


void EK(int s, int t)
{
    int increase = 0;
    while ( (increase = bfs(s, t)) != -1)
    {
        int k = t;
        while (k != s)
        {
            int last = pre[k];
            g[last][k] -= increase;
            g[k][last] += increase;
            k = last;
        }
        maxflow += increase;
    }
}
int main()
{
    LOACL
    cin >> m >> n;
    REP(i, 1, m)
    {
        cin >> x >> y >> z;
        g[x][y] += z;
    }
    EK(1, n);
    cout << maxflow;
}
View Code

 2Dinic  算法  BFS 分层 DFS 找最大流

#include<bits/stdc++.h>
using namespace std;
#define LOACL  freopen("in","r",stdin);\
         freopen("out","w",stdout); 
#define FASTIO  ios::sync_with_stdio(false);
#define CLOCK cout<<1.*clock()/CLOCKS_PER_SEC<<"ms"<<"\n";


const int   inf = 987654321;
const int    sz = (int)100010;
const int   mod = (int)1e9 + 7;
const int sqrtn = 300; 

#define add(u,v,w) e[++tot]=(edge){v,head[u],w},head[u]=tot; 
#define CLR(arr,val) memset(arr,val,sizeof(arr)) 
#define DBG(x) cout<<(#x)<<"="<<x<<endl
#define DBG2(x,y) cout<<(#x)<<"="<<x<<"\t"<<(#y)<<"="<<y<<endl
#define DBG3(x,y,z) cout<<(#x)<<"="<<x<<"\t"<<(#y)<<"="<<y<<"\t"<<(#z)<<"="<<z<<endl
 

#define FOR(i, a, b)  for(int i=(a); i<(b); i++)
#define REP(i, a, b)  for(int i=(a); i<=(b); i++)
#define DOWN(i, a, b) for(int i=(a); i>=(b); i--)
#define Loop(i,u) for(int i =head[u];i;i=e[i].nxt)

#define all(x) x.begin(),x.end()
#define low(x) (x)&(-x)
#define pb push_back
typedef long long ll; 
typedef double dl; 
struct edge
{
    int v,nxt,w;
}e[sz<<1];
int head[sz],tot=-1,level[sz];
int n,m,s,t,u,v,w;
int bfs(int s,int t)
{
    CLR(level,0);
    level[s]=1;
    queue<int>q ;
    q.push(s);
    while(!q.empty())
    {
        int v =q.front();q.pop();
        Loop(i,v)
        {
            if(e[i].w> 0 &&!level[e[i].v])
            {
                level[e[i].v]=level[v]+1;
                q.push(e[i].v);
            }
        }
    }
    return level[t];
}
int dfs(int v,int t,int f)
{
    if(v==t) return f;
    int add =0 ;
    Loop(i,v)
    {
        if(e[i].w> 0 && level[v]+1==level[e[i].v])
        {
            int d =dfs(e[i].v,t,min(f-add,e[i].w));
            if(d>0)
            {
                e[i].w-=d;
                e[i^1].w+=d;
                add+=d;
            }
            else level[e[i].v] =-1;
        }

        if(add>=f)break;
    }
    return add;
}
int Dinic(int s,int t)
{
    int flow = 0;
    while(bfs(s,t))
        flow+=dfs(s,t,0x3f3f3f3f);
    return flow;
}

int main()
{
    LOACL
    cin>>n>>m>>s>>t;
    REP(i,1,m) 
    {
        cin>>u>>v>>w;
        add(u,v,w);add(v,w,0);
    }
    cout<<Dinic(s,t);
}
View Code

 费用流 EK算法 spfa 找增广路 + 尾部合并

#include<bits/stdc++.h>
using namespace std;
#define LOACL  freopen("in","r",stdin);\
         freopen("out","w",stdout);
const int    sz = 50010;
const int inf = 0x3f3f3f3f;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define REP(i, a, b)  for(int i=(a); i<=(b); i++)
#define Loop(i,u) for(int i = head[u];i!=-1;i=e[i].nxt)
int n, m, s, t, u, v, w, f;
struct edge
{
    int v, nxt, w, f;
} e[sz << 1];
int tot = -1, head[sz], pre[sz], inq[sz], dist[sz], incf[sz], maxflow, ans;

void add(int u, int v, int w, int f)
{
    e[++tot] = (edge) {v, head[u], w, f}, head[u] = tot;
}
 
bool spfa(int s, int t)
{
    fill(dist, dist + n + 1, INT_MAX);
    CLR(inq, 0);
    queue<int>q ;
    q.push(s);
    inq[s] = 1;
    dist[s] = 0;
    incf[s] = inf;
    while(!q.empty()) 
    {
        int v = q.front();q.pop();
        inq[v]=0;
        Loop(i,v)
        {
            if(e[i].w>0 && dist[e[i].v]>dist[v]+e[i].f)
            {
                dist[e[i].v]=dist[v]+e[i].f;
                incf[e[i].v]=min(e[i].w,incf[v]);
                pre[e[i].v]=i;
                if(!inq[e[i].v])
                {
                    q.push(e[i].v);
                    inq[e[i].v]=1;
                }
            }
        }
    }
    return dist[t]!=INT_MAX;
}
void update(int s, int t)
{
    int x = t;
    while (x != s)
    {
        int i = pre[x];
        e[i].w -= incf[t];
        e[i ^ 1].w += incf[t];
        x = e[i ^ 1].v;
    }
    maxflow += incf[t];
    ans += dist[t] * incf[t];
}
void EK(int s, int t)
{
    while (spfa(s, t)) update(s, t);
}
 
int main()
{
    LOACL
    CLR(head,-1);
    cin >> n >> m >> s >> t;
    REP(i, 1, m)
    {
        cin >> u >> v >> w >> f;
        add(u, v, w, f); add(v, u, 0, -f);
    }
    EK(s, t);
    cout << maxflow << " " << ans << endl;
}
View Code

 

posted @ 2018-05-19 15:36  pg633  阅读(139)  评论(0编辑  收藏  举报