洛谷 P2153

这道题,看上去就发现是一个最小费用最大流了,这里还是用的 spfa 写的

 

首先需要注意一点,每个十字路口只能走一次,那么还是运用我们的拆点方法,来限制入点到出点,

第二次接触带有最小费用的最大流。。。

下边这些话摘选自一个大犇的博客:https://blog.csdn.net/liusu201601/article/details/79443323

解题思路:

1、请结合最大流的模板对比学习,会更加容易搞到懂;

2、这题因为每条边的流量为 1,所以,是个良心的过渡型模板题,但是费用流和最大流在实现上有一个函数的区别:

    1)最大流:是用 bfs 将点分层,然后 跑 dfs 推流量;

    2)费用流:还是用 bfs 分层,但是(按最小费用)来分层,其实就是跑 spfa(spfa不懂的朋友,下次咱们再复习);

    3)每次 spfa 的过程,用 a[x].f 记录来路;跑完一次完整的spfa之后,可以算出(当前这次流量)的最小费用;

    4)根据 a[x].f 的记录,用循环往回跑,找出这次用过的边,做一下流量反向。

    5)其实基础思维和最大流差不多,只是分层的机制改成了费用,并且将 dfs 函数 省掉(感觉会慢一点点,猜的)

3、构图也比较简单,因为每个点只能跑一次,直接拆点就可以了。

首先 我的 bfs 思路是设的父节点。。因为以前搞过一个模板。。

而且对于每个点 i+n 是出点 , i 是入点 ,cap[ a ] [ b ] 设为 1 cost [ a ] [ b ] = c 

然后 spfa 跑一下,再根据父节点跑一边增广路,多跑几次 spfa 直到无路可走。

mxflow 就是 要跑几次, mxcost 就是我们最小距离(费用)

 

以下是 AC 代码

 

 

#include
#include
#include
#include
using namespace std;
const int maxn = 500;
const int maxm = 405;
const int INF = 0x3f3f3f3f;
int n,m;
int mxflow,mxcost;
int flow[maxn],vis[maxn];
int pre[maxn],dis[maxn];
int cost[maxm][maxm];
int cap[maxm][maxm];
int st,en;
int bfs()
{
    queueq;
    memset(pre,-1,sizeof(pre));
    memset(dis,INF,sizeof(dis));
    memset(flow,0,sizeof(flow));
    q.push(st);
    pre[st] = 0;
    dis[st] = 0;
    vis[st] = 1;
    flow[st] = INF;
    while(q.size())
    {
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for(int i=1;i<2*n;i++)
        {
            if(cap[u][i]>0 && dis[i] >  dis[u] + cost[u][i])
            {
                dis[i] = dis[u] + cost[u][i];
                flow[i] = min(cap[u][i], flow[u]);
                pre[i] = u;
                if(!vis[i])
                {
                    vis[i] = 1;
                    q.push(i);
                }
            }
        }
    }
    if(pre[en] == -1)
        return -1;
    else
        return flow[en];
}

void maxflow()
{
    int rec;
    while(true)
    {
        rec = bfs();
        if(rec == -1)
            return;
        int t = en;
        while(t!=st)
        {
            cap[pre[t]][t] -= rec;
            cap[t][pre[t]] += rec;
            t = pre[t];
        }
        mxflow += rec;
        mxcost += rec*dis[en];
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    st = 1, en = n;
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        int te;
        if(a==1) te = 1;
        else te = a + n;
        cap[te][b] = 1;
        cost[te][b] = c;
        cost[b][te] = -c;
    }
    for(int i=2;i

 

你可能感兴趣的:(洛谷)