zoukankan      html  css  js  c++  java
  • HDU 1853Cyclic Tour(网络流之最小费用流)

    题目地址:HDU1853

    费用流果然好奇妙。

    。还能够用来推断环。。。假设每一个点都是环的一部分并且每一个点仅仅能用到一次的话,那每一个点的初度入度都是1,这就能够利用网络流来解决,仅仅要拆点令其流量为1。就限制了每一个点仅仅能用一次,每次左边的连到右边的。就相当于左边点的一次初度和右边的点的一次入度。非常easy想象出来。

    最后仅仅要推断总流量是否为n就可以。由于假设总流量为n的话。说明每一个点都出了一次度。每一个点都入了一次度。并且由于拆点的流量限制。充分说明了每一个点的初度入度都是1.进而说明了每一个点都在环里。然后输出最后的最小费用流即为最短距离。

    代码例如以下:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <ctype.h>
    #include <queue>
    #include <map>
    #include <algorithm>
    
    using namespace std;
    const int INF=0x3f3f3f3f;
    int head[300], s, t, cnt, flow, cost;
    int vis[300], d[300], q[100000], cur[300];
    struct node
    {
        int u, v, cap, cost, next;
    }edge[100000];
    void add(int u, int v, int cap, int cost)
    {
        edge[cnt].v=v;
        edge[cnt].cap=cap;
        edge[cnt].cost=cost;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    
        edge[cnt].v=u;
        edge[cnt].cap=0;
        edge[cnt].cost=-cost;
        edge[cnt].next=head[v];
        head[v]=cnt++;
    }
    int spfa()
    {
        memset(d,INF,sizeof(d));
        memset(vis,0,sizeof(vis));
        d[s]=0;
        cur[s]=-1;
        int f1=0 ,f2=0, i, minflow=INF;
        q[f1++]=s;
        while(f1>=f2)
        {
            int u=q[f2++];
            vis[u]=0;
            for(i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                if(d[v]>d[u]+edge[i].cost&&edge[i].cap)
                {
                    d[v]=d[u]+edge[i].cost;
                    if(minflow>edge[i].cap)
                    {
                        minflow=edge[i].cap;
                    }
                    cur[v]=i;
                    if(!vis[v])
                    {
                        q[f1++]=v;
                        vis[v]=1;
                    }
                }
            }
        }
        if(d[t]==INF) return 0;
        flow+=minflow;
        cost+=minflow*d[t];
        for(i=cur[t];i!=-1;i=cur[edge[i^1].v])
        {
            edge[i].cap-=minflow;
            edge[i^1].cap+=minflow;
        }
        return 1;
    }
    int main()
    {
        int n, m, i, a, b, c;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(head,-1,sizeof(head));
            cnt=0;
            s=0;
            t=2*n+1;
            flow=0;
            cost=0;
            for(i=1;i<=n;i++)
            {
                add(s,i,1,0);
                add(i+n,t,1,0);
            }
            while(m--)
            {
                scanf("%d%d%d",&a,&b,&c);
                add(a,b+n,1,c);
            }
            while(spfa());
            if(flow!=n)
                printf("-1
    ");
            else
                printf("%d
    ",cost);
        }
        return 0;
    }
    


  • 相关阅读:
    Note/Solution 转置原理 & 多点求值
    Note/Solution 「洛谷 P5158」「模板」多项式快速插值
    Solution 「CTS 2019」「洛谷 P5404」氪金手游
    Solution 「CEOI 2017」「洛谷 P4654」Mousetrap
    Solution Set Border Theory
    Solution Set Stirling 数相关杂题
    Solution 「CEOI 2006」「洛谷 P5974」ANTENNA
    Solution 「ZJOI 2013」「洛谷 P3337」防守战线
    Solution 「CF 923E」Perpetual Subtraction
    KVM虚拟化
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5259677.html
Copyright © 2011-2022 走看看