zoukankan      html  css  js  c++  java
  • HDU 3376 && 2686 方格取数 最大和 费用流裸题

    题意:

    1、一个人从[1,1] ->[n,n] ->[1,1] 

    2、仅仅能走最短路

    3、走过的点不能再走

    问最大和。

    对每一个点拆点限流为1就可以满足3.

    费用流流量为2满足1

    最大费用流,先给图取负,结果再取负,满足2

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <math.h>
    #include <queue>
    #include <set>
    #include <algorithm>
    #include <stdlib.h>
    
    #define N 605*605*2
    #define M N*2
    #define inf 1<<29
    #define ll int
    
    using namespace std;
    
    //双向边,注意RE
    //注意 点标必须是 [0 - 汇点]
    struct Edge{
        ll from, to, flow, cap, nex, cost;
    }edge[M*2];
    
    ll head[N], edgenum;
    void add(ll u,ll v,ll cap,ll cost){//网络流要加反向弧
        Edge E={u, v, 0, cap, head[u], cost};
        edge[edgenum]=E;
        head[u]=edgenum++;
    
        Edge E2={v, u, 0, 0, head[v], -cost}; //这里的cap若是单向边要为0
        edge[edgenum]=E2;
        head[v]=edgenum++;
    }
    ll D[N], P[N], A[N];
    bool inq[N];
    bool BellmanFord(ll s, ll t, ll &flow, ll &cost){
        for(ll i=0;i<=t;i++) D[i]= inf;
    
        memset(inq, 0, sizeof(inq));
        D[s]=0;  inq[s]=1; P[s]=0; A[s]=inf;
    
        queue<ll> Q;
        Q.push( s );
        while( !Q.empty()){
            ll u = Q.front(); Q.pop();
            inq[u]=0;
            for(ll i=head[u]; i!=-1; i=edge[i].nex){
                Edge &E = edge[i];
                if(E.cap > E.flow && D[E.to] > D[u] +E.cost){
                    D[E.to] = D[u] + E.cost ;
                    P[E.to] = i;
                    A[E.to] = min(A[u], E.cap - E.flow);
                    if(!inq[E.to]) Q.push(E.to) , inq[E.to] = 1;
                }
            }
        }
        if(D[t] == inf) return false;
        flow += A[t];
        cost += D[t] * A[t];
        ll u = t;
        while(u != s){
            edge[P[u]].flow += A[t];
            edge[P[u]^1].flow -= A[t];
            u = edge[P[u]].from;
        }
        return true;
    }
    
    ll Mincost(ll s,ll t){//返回最小费用
        ll flow = 0, cost = 0;
        while(BellmanFord(s, t, flow, cost));
        return cost;
    }
    void init(){memset(head,-1,sizeof head); edgenum = 0;}
    ll n;
    ll Hash(ll x,ll y){return (x-1)*n+y;}
    ll Hash2(ll x,ll y){return n*n+(x-1)*n+y;}
    ll mp[605][605];
    int main(){
        ll i, j, u, v, cost;
        while(~scanf("%d",&n)){
            init();
            for(i=1;i<=n;i++)for(j=1;j<=n;j++)scanf("%d",&mp[i][j]);
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=n;j++)
                {
                    add(Hash(i,j),Hash2(i,j),1,-mp[i][j]);
                    u = Hash2(i,j);
                    if(i!=n)
                    {
                        v = Hash(i+1,j);
                        add(u,v,3,0);
                    }
                    if(j!=n)
                    {
                        v = Hash(i,j+1);
                        add(u,v,3,0);
                    }
                }
            }
    		add(Hash(1,1), Hash2(1,1), 1, 0);
    		add(Hash(n,n), Hash2(n,n), 1, 0);
            printf("%d
    ",-Mincost(Hash(1,1), Hash2(n,n)));
        }
        return 0;
    }
    
    



  • 相关阅读:
    PE格式详细讲解10 系统篇10|解密系列
    复杂的数据类型1 C++快速入门07
    复杂的数据类型2 C++快速入门08
    复杂的数据类型2 C++快速入门08
    复杂的数据类型1 C++快速入门07
    PE格式详细讲解10 系统篇10|解密系列
    Win32基础知识1 Win32汇编语言002
    开题篇 Win32汇编语言001
    开题篇 Win32汇编语言001
    Win32基础知识1 Win32汇编语言002
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4246050.html
Copyright © 2011-2022 走看看