首页 > 代码库 > [网络流dinic]日常翻新

[网络流dinic]日常翻新

之前的排版简直辣眼睛,重写一遍好了

模板题是草地排水poj1273

网络流的基础思想就是瞎基本搜

但是搜要搜得有技巧,有特色

最简单的搜,无限深搜直到终点

稍微改进一下,宽搜先标号然后按层搜

再改进一下,把某些确定不再使用的点剔除

要点在于建立反向边给自己一个反悔的机会,用^1找到反向边

技术分享
#include <stdio.h>
#include <queue>
#include <algorithm>
#include <string.h>
using namespace std;
const int N=205;
const int M=405;
int m,n,s,last[N],level[N];
struct edge
{
    int v,w,n;
}e[M];
void add(int u,int v,int w)
{
    e[s]=(edge){v,w,last[u]},last[u]=s++;
    e[s]=(edge){u,0,last[v]},last[v]=s++;
}
int BFS()
{
    memset(level,-1,sizeof(level));
    queue<int>q;
    q.push(1);level[1]=0;
    while(!q.empty())
    {
        int t=q.front();q.pop();
        for (int i=last[t];~i;i=e[i].n)
        {
            if(e[i].w&&level[e[i].v]==-1)
                q.push(e[i].v),level[e[i].v]=level[t]+1;
        }
    }
    return level[n]!=-1;
}
int DFS(int a,int b)
{
    if (a==n) return b;
    int r=0;
    for (int i=last[a];~i&&b>r;i=e[i].n)
    {
        if (level[a]+1==level[e[i].v]&&e[i].w)
        {
            int t=DFS(e[i].v,min(b-r,e[i].w));
            e[i].w-=t;e[i^1].w+=t;r+=t;
        }
    }
    if (!r) level[a]=-1;
    return r;
}
int dinic()
{
    int ans=0,tmp;
    while(BFS())while(tmp=DFS(1,0x3fffffff))ans+=tmp;
    return ans;
}
int main()
{
    while(scanf ("%d %d",&m,&n)!=EOF)
{
    memset (last,-1,sizeof(last));
        s=0;
    for (int i=1;i<=m;i++)
    {
        int u,v,w;
        scanf ("%d %d %d",&u,&v,&w);
        add(u,v,w);
        //add(v,u,0);
    }
    printf ("%d\n",dinic());
}
}
View Code

就是这样,喵~


最后一行献给可爱的男孩子们


 

[网络流dinic]日常翻新