洛谷 P2153 [SDOI2009]晨跑 网络流 最小费用最大流 Dinic+Spfa

题目链接:

https://www.luogu.com.cn/problem/P2153

参考博客:

https://siyuan.blog.luogu.org/solution-p2153

算法:1:最小费用最大流 Dinic+Spfa

思路:

1:首先我们发现需要求路程最短,天数尽量长。那么我们可以考虑最小费用最大流,其中路程为费用,天数为流量

2:由于每个点只能被访问 1 次,那么我们进行拆点,将 i拆成 i1 和 i2,其中 i1 和 i2之间连边 (i1,i2,1,0)(容量为 1 ,费用为 0 ),对于有向图的每条边 (u,v,w) 连边 (u2,v1,1,w) 和其反向边 (v1,u2,0,−w)

3:又因为 1和 n 可以多次经过,那么源点和汇点分别为 s2​ 和 t1​ ,然后直接跑网络流即可

样例图解:

扫描二维码关注公众号,回复: 9950793 查看本文章

代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn=4e2+1,maxm=4e4+4e2+1,inf=0x7fffffff;
int n,m,s,t,a,b,c,tot=1,head[maxn],dis[maxn],flow[maxn],pre[maxn],last[maxn],maxflow,mincost;
bool vis[maxn];
queue<int>q;

struct edge
{
    int to,next,w,dis;
}e[maxm];

void addedge(int x,int y,int w,int dis)
{
    e[++tot].to=y;e[tot].w=w;e[tot].dis=dis;e[tot].next=head[x];head[x]=tot;
    e[++tot].to=x;e[tot].w=0;e[tot].dis=-dis;e[tot].next=head[y];head[y]=tot;
}

bool spfa()
{
    memset(dis,0x7f,sizeof(dis));
    memset(last,0,sizeof(last));
    memset(vis,0,sizeof(vis));
    flow[s]=inf;
    q.push(s);vis[s]=1;dis[s]=0;pre[t]=-1;
    while(!q.empty())
    {
        int now=q.front();q.pop();
        vis[now]=0;
        for(int i=head[now];i;i=e[i].next)
        {
            int y=e[i].to;
            if(e[i].w>0&&dis[y]>dis[now]+e[i].dis)
            {
                dis[y]=dis[now]+e[i].dis;
                pre[y]=now;
                last[y]=i;
                flow[y]=min(flow[now],e[i].w);
                if(!vis[y])
                {
                    q.push(y);
                    vis[y]=1;
                }
            }
        }
    }
    if(pre[t]==-1)return 0;
    int now=t;
    maxflow+=flow[t];
    mincost+=flow[t]*dis[t];
    while(now!=s)
    {
        e[last[now]].w-=flow[t];
        e[last[now]^1].w+=flow[t];
        now=pre[now];
    }
    return 1;
}

int main()
{
    ios::sync_with_stdio(0);
    scanf("%d %d",&n,&m);
    s=1+n,t=n;
    for(int i=1;i<=n;i++)addedge(i,i+n,1,0);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&a,&b,&c);
        addedge(a+n,b,1,c);
    }
    while(spfa());
    printf("%d %d\n",maxflow,mincost);
    return 0;
}
发布了164 篇原创文章 · 获赞 82 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/aiwo1376301646/article/details/104321348
今日推荐