• 【题解】Luogu P2153 [SDOI2009]晨跑


    原题传送门

    一眼应该就能看出是费用流

    因为每个交叉路口只能通过一次,所以我们进行拆点,连一条流量为1费用为0的边

    再按照题目给的边(是单向边)建图

    跑一下MCMF就行了

    拆点很套路的~

    #include <bits/stdc++.h>
    #define N 205
    #define M 20005
    #define inf (1<<30)
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf; 
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline int Min(register int a,register int b)
    {
        return a<b?a:b;
    }
    struct node{
        int to,next,v,c;
    }e[(M<<2)+(N<<1)];
    int head[N<<1],cnt=1;
    inline void add(register int u,register int v,register int val,register int cost)
    {
        e[++cnt]=(node){v,head[u],val,cost};
        head[u]=cnt;
    }
    int n,m,s,t,maxflow=0,mincost=0;
    int vis[N<<1],dist[N<<1];
    inline bool spfa()
    {
        memset(vis,0,sizeof(vis));
        memset(dist,0x3f,sizeof(dist));
        dist[s]=0;
        vis[s]=1;
        queue<int> q;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(register int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if(dist[v]>dist[u]+e[i].c&&e[i].v)
                {
                    dist[v]=dist[u]+e[i].c;
                    if(vis[v]==0)
                    {
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
        return dist[t]!=0x3f3f3f3f;
    }
    inline int dfs(register int u,register int flow)
    {
        if(u==t)
        {
            vis[t]=1;
            maxflow+=flow;
            return flow;
        }
        int used=0;
        vis[u]=1;
        for(register int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if((vis[v]==0||v==t)&&e[i].v&&dist[v]==dist[u]+e[i].c)
            {
                int tmp=dfs(v,Min(e[i].v,flow-used));
                if(tmp)
                {
                    mincost+=e[i].c*tmp;
                    used+=tmp;
                    e[i].v-=tmp;
                    e[i^1].v+=tmp;
                }
                if(used==flow)
                    return used;
            }
        }
        return used;
    }
    inline void MCMF()
    {
        while(spfa())
        {
            vis[t]=1;
            while(vis[t])
            {
                memset(vis,0,sizeof(vis));
                dfs(s,inf);
            }
        }
    }
    int main()
    {
        n=read(),m=read();
        s=1,t=n;
        for(register int i=2;i<n;++i)
            add(i,i+n,1,0),add(i+n,i,0,0);
        for(register int i=1;i<=m;++i)
        {
            int u=read(),v=read(),cost=read();
            if(u==1)
                add(u,v,1,cost),add(v,u,0,-cost);
            else if(v==n)
                add(u+n,v,1,cost),add(v,u+n,0,-cost);
            else
                add(u+n,v,1,cost),add(v,u+n,0,-cost);
        }
        MCMF();
        write(maxflow),putchar(' '),write(mincost);
        return 0;
    } 
    
  • 相关阅读:
    递归初级——第39级台阶
    排序——快速排序(尾递归优化)
    排序——快速排序(优化小数组时的排序方案 )
    排序——快速排序(三数取中法和优化不必要交换)
    排序——归并排序(递归实现+迭代实现 )
    超详细Hexo+Github博客搭建小白教程
    每日算法系列【LeetCode 1031】两个非重叠子数组的最大和
    每日算法系列【LeetCode 330】按要求补齐数组
    5W2H | 关于写博客的七点反思
    每日算法系列【LeetCode 124】二叉树中的最大路径和
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10321791.html
Copyright © 2020-2023  润新知