2018年1月29日训练日记

今天的主要任务是看网络流的资料。虽然看了3个ppt和两个word以及一些例题,但是还是感觉不懂。这里先把概念贴一下。。。

by 某个dalao的博客:

网络流是指给定一个有向图,和两个点–源点S和汇点T,点之间有连边, 每条边有一个容量限制,可以看作水管,网络流就是指由S点流到T点的一个可行流。 
最大流就是指所有可行流里面最大的流。
通俗的讲,就是由若干个运货点,一个是起点,一个是终点,有一些运货点由路相连,每条路有容量限制,走过那条路时运送的货物不能超过其中的容量限制,求最大流就是求从起点运送尽量多的货物到终点,到达终点的货物个数。

还是比较容易理解的。但是很快会发现,最难的还是建图。

有些题目直接构图点的数量或边的数量会非常大,会超时或爆内存,因此可以通过缩点来进行优化。即:

如果几个节点的来源完全相同,则可以把它们合成一个。
如果几个节点的去向完全相同,则可以把它们合成一个。
如果从u到v有一条容量为∞的边,并且v除了u以外没有别的流量来源,则可以把这它们合并成一个。

个人Dinic算法模板:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define rep(i,a,b) for(register int i=(a),iend=(b);i<=iend;++i)
inline int read()
{
    register int c=getchar(),fg=1,sum=0;
    while(c>'9'||c<'0') {if(c == '-')fg = -1;c=getchar();}
    while(c<='9'&&c>='0'){sum=sum*10+c-'0';c=getchar();}
    return fg*sum;
}
const int mx=100010;
const int inf=0x3f3f3f3f;
int n,m,t;
int he[mx],d[mx];
struct edge{
    int v,nex;
    int w;
}a[mx];
void init()
{
 t=0;
 memset(he,-1,sizeof(he));
}
void add(int u,int v,int w)
{
    a[t].v=v;
    a[t].nex=he[u];
    a[t].w=w;
    he[u]=t++;
}
int bfs()
{
    memset(d,-1,sizeof(d));//zhu yi shi -1
    queue<int> q;
    q.push(n);
    d[n]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=he[u];i!=-1;i=a[i].nex)
        {
            int v=a[i].v;
            if(a[i^1].w&&d[v]==-1)
            {
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[1]!=-1;
}
int dfs(int x,int low)
{
    if(x==n)return low;
    int k;
    for(int i=he[x];i!=-1;i=a[i].nex)
    {
        int v=a[i].v;
        if(a[i].w&&d[v]==d[x]-1)
        {
            k=dfs(v,min(low,a[i].w));
            if(k>0){
                a[i].w-=k;
                a[i^1].w+=k;
                return k;
            }
        }
    }
    return 0;
}
int main()
{
    int T,cas=1;
    while(scanf("%d",&T)!=EOF)
    {
        while(T--)
        {
        scanf("%d%d",&n,&m);
        init();
        rep(i,1,m)
        {
            int x,y,z;
            x=read(),y=read(),z=read();
            add(x,y,z);
            add(y,x,0);
        }
        int ans=0,k;
        while(bfs())
        {
            k=dfs(1,inf);
            ans+=k;
        }
        printf("Case %d: %d\n",cas++,ans);
        }
    }
    return 0;
}

个人犯过的错误:

初始化一定不能错,搞清楚。是否添加源点和汇点,n相应的值要怎样变化,如果不需要添加,源点和汇点是哪两个。

比较常见的两种构图,一种是邻接矩阵,一种是链式前向星。

最后引用大牛的话:

虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。

加油!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值