[网络流]hdu3046(Dinic)

首先我想讲一下网络流的基础。

第一,要明白一些基础的概念,否则对后面的理解会有一定的影响。这里只列出常用的,列太多会影响阅读效率的。

底图:如果把一个有向图的每条边的方向都去掉,得到的无向图称为原有图的底图。

途径:图G中点边连续交替出现的序列称为G的一条途径。

迹:图G中边不重复出现的途径称为迹。

路:图G中顶点不重复出现的迹称为路。

网络的基本概念:

定义:一个网络N=(V,A)是指一个连通无环且满足下列条件的有向图:

1.有一个定点子集X,其每个顶点的入度都是0;

2.有一个与X不相交的顶点子集Y,其每个顶点的出度都为0;

3.每条弧都有一个非负的权值,称为弧的容量。

上述网络N记作N(V,X,Y,A,C),其中X为网络的源点集,Y称为网络的汇点集,V和A分别称为顶点集和弧集。C为网络的容量函数。

网络的可行流:

网络N=(V,X,Y,A,C)中的一个可行流是指定义在A上的一个整值函数f,使得:

1.对任意a属于A,0<=f(a)<=c(a)(容量约束);

2.对任意v属于 V-(XUY),f(v)=f’(v)(流量守恒);

其中f(v)表示点v的入弧的流量之和,f’(v)表示点v的出弧的流量之和。

最大流最小割定理:在任一网络中,最大流的流量等于最小割的容量。

此定理对于如何求最大流并没有什么用处,但是可以用他来证明最大流的正确性。

最大流的求解:

求网络中的最大流基本思想都是不断地增加流量,直到不能再增加为止。这就引入了可增路的概念。

:设u,v是网络N中任意两点,P是N的底图中的一条连接uv的路,若规定P的走向为从u到v,则称这样规定了走向的路P为网络N中一条从u到v的路,简称u-v路。特别的,一条从源点x到汇点y的路称为x-y路。

正向弧就是路中的边在原图中是否是正向弧。不是就是反向弧。

可增路:假设f是网络的一个可行流,u是N中任意一点,P是网络N中的一条x-u路,如果对路P上的任一弧a,都有:

1.若弧a是P的正向弧,则c(a)-f(a)>0;

2.若弧a是P的反向弧,则f(a)>0;

则P称为N的一条可增x-u路。特别的,一条f可增x-y路称为 N的一条f可增路。

对于N中任意一条f可增路P和P上任意一条弧a,假设

△f(a)= c(a)-f(a) (正向弧)

f(a) (反向弧)

则可增路的可增加流量为△f(P)=min{△f(a)};称为可增量。

最大流Dinic算法:

Dinic算法利用分层的思想对网络进行一些处理,简化了一些操作。

1.增量网络(残余网络)

对于网络N和N上的可行流f,构造一个新的网络N(f)=(V,X,Y,A(f),C’)中A(f)及容量函数C’定义如下:

(为何这么诡异,把这句好敲出来博客页面就显示不出下面的两张图和部分文字。。无奈,只好截图了。。。噗噗噗。。)

2.若(u,v)属于A并且f(u,v)>0,则(v,u)属于A(f),并且c’(u,v)=f(u,v);

分层就是bfs一遍扫描网络,求出每个点到源点的最短距离。

对分层后的网络进行下一步的操作就可以得到辅助网络。

辅助网络:对于增量网络N(f)进行分层后,删除层数不低于y的顶点,再删除从高层指向低层的弧和同层之间的弧。

其实代码中并没有很清晰的看到辅助网络的身影,直接是bfs分层,dfs计算△f(a),直到bfs不能达到汇点。

好了,说一下本题的题意吧。

题意:就是在一个网格中有些是羊,有两个是灰太狼和红太狼,问怎样用最少的栏杆拦截使小羊安全。

分析:

每个点都有向相邻点的连线,容量为1,狼都连向汇点,羊都连向源点,容量为inf。求最大流。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
#define read freopen("q.in","r",stdin)
#define maxn 40004
#define inf 0x7fffffff
int edgeNum,n,m;
int d[maxn],head[maxn];

struct Edge
{
    int to,flow,next;
}edge[maxn*4];
int from,to;
void add(int u,int v,int flow)
{
    edge[edgeNum].to=v;edge[edgeNum].flow=flow;edge[edgeNum].next=head[u];head[u]=edgeNum++;
    edge[edgeNum].to=u;edge[edgeNum].flow=0;edge[edgeNum].next=head[v];head[v]=edgeNum++;
}

bool bfs()
{
    memset(d,0,sizeof(d));
    int i,k,j;
    queue<int> q;
    d[from]=1;
    q.push(from);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(!d[v] && edge[i].flow>0)
            {
                d[v]=d[u]+1;
                q.push(v);
                if(v==to)return true;
            }
        }
    }
    return false;
}

int dfs(int u,int flow)
{
    if(u==to || flow==0)return flow;
    int i,j,k;
    int cap=flow;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(d[v]==d[u]+1 && edge[i].flow>0)
        {
            int x=dfs(v,min(cap,edge[i].flow));
            cap-=x;
            edge[i].flow-=x;
            edge[i^1].flow+=x;
            if(cap==0)return flow;
        }
    }
    return flow-cap;
}

int dinic()
{
    int sum=0;
    while(bfs())sum+=dfs(from,inf);
    return sum;
}
int main()
{
//  read;
    int i,j,x,cas=1;
    while(~scanf("%d%d",&n,&m))
    {
        from=n*m+1;to=n*m+2;
        edgeNum=0;
        memset(head,-1,sizeof(head));
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                scanf("%d",&x);
                if(x==1)add(from,(i-1)*m+j,inf);
                if(x==2)add((i-1)*m+j,to,inf);
                if(i-1>=1 )add((i-1)*m+j,(i-2)*m+j,1);
                if(j-1>=1 )add((i-1)*m+j,(i-1)*m+j-1,1);
                if(i+1<=n )add((i-1)*m+j,i*m+j,1);
                if(j+1<=m )add((i-1)*m+j,(i-1)*m+j+1,1);

            }
        }
        int res=dinic();
        cout<<"Case "<<cas++<<":\n"<<res<<endl;
    }
}

ps:我觉得讲算法附上代码很重要。

时间: 2024-11-05 10:40:05

[网络流]hdu3046(Dinic)的相关文章

[知识点]网络流之Dinic算法

// 此博文为迁移而来,写于2014年2月6日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vrg4.html 今天我们来谈谈网络流之Dinic算法.这种算法相比Edmond-Karp算法,更加快速,更加常用.还记得EK吗?每次为了防止流量堵塞,必须进行多次BFS/DFS,非常费时间.而Dinic大叔非常机智的发明了Dinic算法,让这个问题得以解决. Dinic的核心内容是:反复进行BFS绘制出层次图,和DFS进行

POJ 2391 Ombrophobic Bovines (二分,最短路径,网络流sap,dinic,预留推进 )

Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14019   Accepted: 3068 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They h

网络流算法Dinic的Python实现

在上一篇我们提到了网络流算法Push-relabel,那是90年代提出的算法,算是比较新的,而现在要说的Dinic算法则是由以色列人Dinitz在冷战时期,即60-70年代提出的算法变种而来的,其算法复杂度为O(mn^2). Dinic算法主要思想也是基于FF算法的,改进的地方也是减少寻找增广路径的迭代次数.此处Dinitz大师引用了一个非常聪明的数据结构,Layer Network,分层网络,该结构是由BFS tree启发得到的,它跟BFS tree的区别在于,BFS tree只保存到每一层的

「CODVES 1922 」骑士共存问题(二分图的最大独立集|网络流)&amp;dinic

首先是题目链接  http://codevs.cn/problem/1922/ 结果发现题目没图(心情复杂 然后去网上扒了一张图 大概就是这样了. 如果把每个点和它可以攻击的点连一条边,那问题就变成了求二分图的最大独立集了 (二分图最大独立集:即一个点集,集合中任两个结点不相邻),然后就是建图了. 题图非常好心的帮忙染色了,所以我们可以看出来,一个点可以到达的点和它的颜色是不一样的,所以只需要黑白染色就可以了,然后把黑点看作一个集合, 白点看作一个集合,又因为二分图最大独立集= 二分图最大匹配,

初涉网络流[EK&amp;dinic]

主要还是板子 Edmonds-Karp 从S开始bfs,直到找到一条到达T的路径后将该路径增广,并重复这一过程. 在处理过程中,为了应对“找到的一条路径把其他路径堵塞”的情况,采用了建反向弧的方式来实现“反悔”过程. 这种“反悔”的想法和技巧值得借鉴. 1 int maxFlow() 2 { 3 int ret = 0; 4 for (;;) 5 { 6 memset(f, 0, sizeof f); 7 memset(bck, 0, sizeof bck); 8 std::queue<int>

hdu4280网络流之dinic

这题就是个模板题,不过我是第一次写dinic,好久没用链式前向星又不会了... 时间:9126ms #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cassert> #include<iomanip> #incl

(网络流 模板 Dinic) Drainage Ditches --POJ --1273

链接: http://poj.org/problem?id=1273 代码: #include<stdio.h> #include<string.h> #include<queue> #include<algorithm> using namespace std; const int MAXN = 1005; const int oo = 1e9+7; struct Edge { int v, flow, next; }edge[MAXN]; int Hea

POJ 3281 网络流(dinic邻接矩阵、单路增广、多路增广)

思路:刚开始看题就想到怎么建图了,源点连向所有的食物,食物连牛,牛连饮料,饮料连汇点,所有的流量都是1.不过这样建图好后,WA了.原来是一头牛只能单一匹配一组食物和饮料,所以牛得拆点,牛之间得相连,流量为1,以保证单一匹配食物和饮料. 邻接矩阵dinic单路的代码: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #in

poj 1273 裸 网络流 (dinic)

Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage