洛谷P3376 【模板】网络最大流{Dinic算法}

题目

https://www.luogu.org/problemnew/show/P3376


解题思路

【{什么是Dinic算法}引:1、每次以源点为起始点bfs,求出每个点的编号d[i],d[i]表示从源点到i点通过至少几条残余流量大于0的边,能够到达i点。

2、**只有那些满足d[u]+1=d[v]的边(u,v)才被视为存在,然后在这里面不断DFS找增广路并增广(其实随便走都可以),如果没有增广路了,那么返回步骤1,如果BFS不到汇点,证明算法结束。
该算法在第二步DFS有些优化,实现时可以自己想一想。一般不怎么加优化这个算法的效率都很不错了。】**


代码

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std; 
const int inf=100000000; 
queue<int>que;
struct node{
    int x,y,c,next;
}a[200001];
int n,m,s,t,len=-1,cur[10005],last[200001],dis[200001]; 
int minn(int xa,int ya)
{return xa>ya?ya:xa;}
void add(int xa,int ya,int ca)
{
    a[++len].y=ya; a[len].c=ca; a[len].next=last[xa]; last[xa]=len;
    a[++len].y=xa; a[len].c=0; a[len].next=last[ya]; last[ya]=len;
}
bool bfs()//找增广路,分层
{
    memset(dis,0,sizeof(dis)); 
    while (!que.empty()) que.pop(); 
    dis[s]=1; que.push(s); 
    while (!que.empty())
    {
        int u=que.front(); que.pop(); 
        for (int i=last[u];i;i=a[i].next)
        if (a[i].c&&!dis[a[i].y])
        {
            dis[a[i].y]=dis[u]+1; 
            if (a[i].y==t) return 1;    
            que.push(a[i].y); 
        }
    }
    return 0; 
}
int dfs(int xq,int maxf)//修改值
{
    if (xq==t||!maxf) return maxf;
    int ret=0; 
    for (int &i=cur[xq];i;i=a[i].next)
    if (a[i].c&&dis[a[i].y]==dis[xq]+1)
    {
        int f=dfs(a[i].y,min(a[i].c,maxf-ret));
        a[i].c-=f;
        a[i^1].c+=f;
        ret+=f; 
        if (maxf==ret) break; 
    }
    return ret; 
}
int dinic()
{
    int ans=0; 
    while (bfs())
    {
        for (int i=1;i<=n;i++) cur[i]=last[i]; 
        ans+=dfs(s,inf); //累加最大流
    }
    return ans; 
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t); 
    int xx,yy,cc; 
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&xx,&yy,&cc); 
        add(xx,yy,cc);//建图,建图最重要
    }
    printf("%d",dinic());
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/80769164