zoukankan      html  css  js  c++  java
  • POJ 2135 Farm Tour && HDU 2686 Matrix && HDU 3376 Matrix Again 费用流求来回最短路

    累了就要写题解,近期总是被虐到没脾气。

    来回最短路问题貌似也能够用DP来搞。只是拿费用流还是非常方便的。

    能够转化成求满流为2 的最小花费。一般做法为拆点,对于 i 拆为2*i 和 2*i+1。然后连一条流量为1(花费依据题意来定) 的边来控制每一个点仅仅能通过一次。

    额外加入source和sink来控制满流为2。

    代码都雷同,以HDU3376为例。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <map>
    
    #pragma comment(linker, "/STACK:1024000000");
    #define EPS (1e-8)
    #define LL long long
    #define ULL unsigned long long
    #define _LL __int64
    #define INF 0x3f3f3f3f
    #define Mod 6000007
    
    using namespace std;
    
    const int EDGE = 6000000,POINT = 730000;
    
    struct E
    {
        int Max,cost,v,next;
    }edge[EDGE];
    
    int head[POINT];
    
    int Top;
    
    void Link(int u,int v,int w,int cost)
    {
        edge[Top].v = v;
        edge[Top].Max = w;
        edge[Top].cost = cost;
        edge[Top].next = head[u];
        head[u] = Top++;
    }
    
    int Map[610][610];
    
    int dis[POINT],cur[POINT],flow[POINT];
    bool mark[POINT];
    
    void Updata(int site,int flow,int &cost)
    {
        for(;cur[site] != -1; site = edge[cur[site]^1].v)
        {
            edge[cur[site]].Max -= flow;
            edge[cur[site]^1].Max += flow;
            cost += edge[cur[site]].cost * flow;
        }
    }
    
    queue<int> q;
    
    int spfa(int S,int T,int &cost)
    {
        memset(mark,false,sizeof(mark));
        memset(dis,INF,sizeof(dis));
    
        cur[S] = -1,dis[S] = 0,flow[S] = INF;
    
        q.push(S);
    
        int f,t;
    
        while(q.empty() == false)
        {
            f = q.front();
            q.pop();
            mark[f] = false;
    
            for(int p = head[f];p != -1; p = edge[p].next)
            {
                t = edge[p].v;
                if(edge[p].Max && dis[t] > dis[f] + edge[p].cost)
                {
                    dis[t] = dis[f] + edge[p].cost;
                    cur[t] = p;
                    flow[t] = min(flow[f],edge[p].Max);
    
                    if(mark[t] == false)
                    {
                        mark[t] = true;
                        q.push(t);
                    }
                }
            }
        }
    
        if(dis[T] == INF)
            return 0;
        Updata(T,flow[T],cost);
        return flow[T];
    }
    
    int Cal_Max_Flow_Min_Cost(int S,int T,int n)
    {
        int temp,flow = 0,cost = 0;
    
        do
        {
            temp = spfa(S,T,cost);
            flow += temp;
        }while(temp);
        return cost;
    }
    
    inline int Cal(int x,int y,int n)
    {
       return ((x-1)*n+y)*2-1;
    }
    
    int main()
    {
        int n;
        int i,j;
    
        while(scanf("%d",&n) != EOF)
        {
            memset(head,-1,sizeof(head));
            Top = 0;
    
            for(i = 1;i <= n; ++i)
            {
                for(j = 1;j <= n; ++j)
                {
                    scanf("%d",&Map[i][j]);
                    if(i == j && (i == 1 || i == n))
                        Link(Cal(i,j,n),Cal(i,j,n)+1,2,-Map[i][j]);
                    else
                        Link(Cal(i,j,n),Cal(i,j,n)+1,1,-Map[i][j]);
                    Link(Cal(i,j,n)+1,Cal(i,j,n),0,Map[i][j]);
                }
            }
    
            for(i = 1;i <= n; ++i)
            {
                for(j = 1;j <= n; ++j)
                {
                    if(j < n)
                    {
                        Link(Cal(i,j,n)+1,Cal(i,j+1,n),1,0);
                        Link(Cal(i,j+1,n),Cal(i,j,n)+1,0,0);
                    }
                    if(i < n)
                    {
                        Link(Cal(i,j,n)+1,Cal(i+1,j,n),1,0);
                        Link(Cal(i+1,j,n),Cal(i,j,n)+1,0,0);
                    }
                }
            }
    
            printf("%d
    ",-Cal_Max_Flow_Min_Cost(1,n*n*2,n*n*2) - Map[1][1] - Map[n][n]);
        }
        return 0;
    }

  • 相关阅读:
    软件开发过程中应当遵守的原则
    企业架构是什么?
    软件工程的精髓
    PHP获取自然周列表,周开始结束日期,月开始结束时间方法类
    JS替换textarea里的回车换行
    PHP连接PGSQL
    PT与PX的区别
    JQuery 翻页小记
    PHP中替换textarea时的回车换行
    HTML5 CanvasOreilly.Canvas.Pocket.Reference (4)
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/5097025.html
Copyright © 2011-2022 走看看