POJ-1273 Drainage Ditches(最大流入门)

  前述:这周周一做了两个组合数专题的题,依旧是容斥定理的题目,然后就不会了,正好专题延时了,就转向看了看网络流的博客,a了几道最大流的题,有简单的,有比较综合的,也只能不断摸索着前进,简单的构图还是可以想出来的,但是还是没理解拆点的意义所在,就是想不到为什么要拆点,也做了一些简单的尝试,就是把题解上拆点的做法,用不拆点的方法做,可是想法总觉得很好,就是总是wr,看起来我需要用脑子运行一下这个程序,才能知道拆点的真正作用。

  题目:POJ-1273 Drainage Ditches

  题目大意:就是求1到m的最大流,裸的最大流的题目,借着连连模板。

  AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#define maxn 20
#define INF 1e9
using namespace std;
struct edge{
    edge(){};
    edge(int from,int to,int val,int flow):from(from),to(to),val(val),flow(flow){}
    int from,to,val,flow;
};
int n,m;
vector<edge>p;
vector<int>num[maxn];
bool visit[maxn];
int dis[maxn];
int cur[maxn];
void add(int x,int y,int z){
    p.push_back(edge(x,y,z,0));
    p.push_back(edge(y,x,0,0));
    int xx=p.size();
    num[x].push_back(xx-2);
    num[y].push_back(xx-1);
}
bool bfs(int s,int t){
    int i,j;
    memset (visit,0,sizeof(visit));
    queue<int>qq;
    qq.push(s);
    dis[s]=0;
    visit[s]=1;
    while (!qq.empty()){
        int u=qq.front();
        qq.pop();
        for (i=0;i<num[u].size();i++){
            edge& e=p[num[u][i]];
            if (!visit[e.to]&&e.val>e.flow){
                visit[e.to]=1;
                dis[e.to]=dis[u]+1;
                qq.push(e.to);
            }
        }
    }
    return visit[t];
}
int dfs(int x,int t,int val){
    if (x==t||val==0){
        return val;
    }
    int flow=0,f;
    for (int& i=cur[x];i<num[x].size();i++){
        edge& e=p[num[x][i]];
        if (dis[x]+1==dis[e.to]&&(f=dfs(e.to,t,min(val,e.val-e.flow)))>0){
            e.flow+=f;
            p[num[x][i]^1].flow-=f;
            flow+=f;
            val-=f;
            if (val==0)break;
        }
    }
    return flow;
}
int dinic(int s,int t){
    int flow=0;
    while (bfs(s,t)){
        memset (cur,0,sizeof(cur));
        flow+=dfs(s,t,INF);
    }
    return flow;
}
int main(){
    int i,j,k,l,x,y,z,t;
    while (scanf("%d%d",&m,&n)!=EOF){
        p.clear();
        for (i=1;i<=n;i++)num[i].clear();
        for (i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
        }
        printf("%d\n",dinic(1,n));
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值