HDU 3549 最大流模板 dinic

网络流
适用的图 :
在这里插入图片描述
注意上面的唯一

满流:从源点出发的流量 等于 最大流(就是源点发出多少,汇点接受多少)

网络流建模问题:
因为网络流算法是基于有向图并且只有一个源点一个汇点的模型的
必要时候我们必须进行模型的转化
1.无向图转有向图:可以把,u,v之间的无向边变为(u,v),(v,u)两个?向边,容量一样。然后每个边再建立一个反向边,一共四条边。
u、v的实际流量为两者之差。

注:若原图是有向图,则两点之间的实际流量就是两点之间反向路径的权值

2.多个源点、多个汇点:建立一个超级源点,一个超级汇点,分别连接所有的源点和汇点,然后求从超级源点到超级汇点的最大流,新边权视情况而定

hdu 3549
AC 代码1(效率最高)
弧优化

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define maxn 100010
using namespace std;
int point[maxn*2],next1[maxn*2],first[maxn*2],w[maxn*2];
int cur[maxn*2];
int dis[maxn];
int q[maxn];
int n,m,ans,k;

bool bfs();
int dfs(int,int);
int main()
{
    int T ,cnt = 0;
    cin>>T;
    while( T--)
    {
        cnt++;
        k  = 0;
        memset(point,0xff,sizeof(point));
        memset(next1,0xff,sizeof(next1));
        memset(first,0xff,sizeof(first));//0xff  表示 - 1

        scanf("%d%d",&n,&m);
        for(int i = 1,u,v,val; i <= m; i++)
        {

            scanf("%d%d%d",&u,&v,&val);
            point[k] = v;next1[k] = first[u];first[u] = k;w[k++] = val;
            point[k] = u;next1[k] = first[v];first[v] = k;;w[k++] = 0;
        }
        ans = 0;
        while(bfs())
        {
            int tmp = 0;
            while( tmp = dfs(1,0x7fffffff))
                ans += tmp;
        }
        printf("Case %d: %d\n",cnt,ans);

        memset(w,0,sizeof(w));
    }
}
int dfs(int now,int low)
{
    int tmp = 0;
    if(now == n) return low;
    for(int k = cur[now];k != -1;k = next1[k])
    {
        int new1 = point[k];
        cur[now] = k;
        if(dis[new1] == dis[now] + 1 && w[k] > 0 &&  (tmp = dfs(new1,min(low,w[k]))))
        {

            w[k] -= tmp;
            w[k^1] += tmp;
            return tmp;
        }
    }
    return 0;

}
 bool bfs()
 {
    int h,t;
    for(int i = 1;i <= n; i++)
    {
       cur[i] =  first[i];
       dis[i] = -1;//-1
    }
    dis[1] = 0;
    h = 0,t = 1;
    q[1] = 1;
    while(h < t)
    {
        int now =  q[++h];
        int k = first[now];
        while(k != -1)
        {
            int new1 = point[k];
            if(dis[new1] < 0 && w[k] > 0)
            {
                dis[new1] = dis[now] + 1;
                q[++t] = new1;
            }
            k = next1[k];
        }
    }
    return dis[n] > 0?1:0;
 }

AC 代码2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define maxn 100010
using namespace std;
int point[maxn*2],next1[maxn*2],first[maxn*2],w[maxn*2];
int dis[maxn];
int q[maxn];
int n,m,ans,k;

bool bfs();
int dfs(int,int);
int main()
{
    int T ,cnt = 0;
    cin>>T;
    while( T--)
    {
        cnt++;
        k  = 0;
        memset(point,0xff,sizeof(point));
        memset(next1,0xff,sizeof(next1));
        memset(first,0xff,sizeof(first));//0xff  表示 - 1

        scanf("%d%d",&n,&m);
        for(int i = 1,u,v,val; i <= m; i++)
        {

            scanf("%d%d%d",&u,&v,&val);
            point[k] = v;next1[k] = first[u];first[u] = k;w[k++] = val;
            point[k] = u;next1[k] = first[v];first[v] = k;w[k++] = 0;
        }
        ans = 0;
        while(bfs())
        {
            int tmp = 0;
            while( tmp = dfs(1,0x7fffffff))
                ans += tmp;
        }
        printf("Case %d: %d\n",cnt,ans);

        memset(w,0,sizeof(w));
    }
}
int dfs(int now,int low)
{
    int tmp = 0;
    if(now == n) return low;
    for(int k = first[now];k != -1;k = next1[k])
    {
        int new1 = point[k];
        if(dis[new1] == dis[now] + 1 && w[k] > 0 &&  (tmp = dfs(new1,min(low,w[k]))))
        {
            w[k] -= tmp;
            w[k^1] += tmp;
            return tmp;
        }
    }
    return 0;

}
 bool bfs()
 {
    int h,t;
    memset(dis,0xff,sizeof(dis));
    dis[1] = 0;
    h = 0,t = 1;
    q[1] = 1;
    while(h < t)
    {
        int now =  q[++h];
        int k = first[now];
        while(k != -1)
        {
            int new1 = point[k];
            if(dis[new1] < 0 && w[k] > 0)
            {
                dis[new1] = dis[now] + 1;
                q[++t] = new1;
            }
            k = next1[k];
        }
    }
    return dis[n] > 0?1:0;
 }

AC代码3(效率最低)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define maxn 100010
using namespace std;
int point[maxn*2],next1[maxn*2],first[maxn*2],w[maxn*2];
int dis[maxn];
int q[maxn];
int n,m,ans,k;

bool bfs();
int dfs(int,int);
int main()
{
    int T ,cnt = 0;
    cin>>T;
    while( T--)
    {
        cnt++;
        k  = 0;
        memset(point,0,sizeof(point));
        memset(next1,0,sizeof(next1));
        memset(first,0,sizeof(first));//0xff  表示 - 1

        scanf("%d%d",&n,&m);
        for(int i = 1,u,v,val; i <= m; i++)
        {

            scanf("%d%d%d",&u,&v,&val);
            point[++k] = v;next1[k] = first[u];first[u] = k;w[k] = val;
            point[++k] = u;next1[k] = first[v];first[v] = k;w[k] = 0;
        }
        ans = 0;
        while(bfs())
        {
            int tmp = 0;
            while( tmp = dfs(1,0x7fffffff))
                ans += tmp;
        }
        printf("Case %d: %d\n",cnt,ans);

        memset(w,0,sizeof(w));
    }
}
int dfs(int now,int low)
{
    int tmp = 0;
    if(now == n) return low;
    for(int k = first[now];k != 0;k = next1[k])
    {
        int new1 = point[k];
        if(dis[new1] == dis[now] + 1 && w[k] > 0 &&  (tmp = dfs(new1,min(low,w[k]))))
        {
            w[k] -= tmp;
            if(k % 2)
               w[k + 1] += tmp;
            else w[k - 1] += tmp;
            return tmp;
        }
    }
    return 0;

}
bool bfs()
{
    int h,t;
    memset(dis,0xff,sizeof(dis));
    dis[1] = 0;
    h = 0,t = 1;
    q[1] = 1;
    while(h < t)
    {
        int now =  q[++h];
        int k = first[now];
        while(k != 0)
        {
            int new1 = point[k];
            if(dis[new1] < 0 && w[k] > 0)
            {
                dis[new1] = dis[now] + 1;
                q[++t] = new1;
            }
            k = next1[k];
        }
    }
    return dis[n] > 0?1:0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43912833/article/details/98870978
今日推荐