Going Home HDU - 1533 (费用流)

Going Home

HDU - 1533

  1 //费用流初探
  2 #include <iostream>
  3 #include <queue>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <algorithm>
  7 using namespace std;
  8 const int inf = 0x3f3f3f3f;
  9 const int maxn = 110;
 10 char gra[maxn][maxn];
 11
 12 const int maxv =  210;
 13 const int maxe = 210 * 210;
 14 struct Edge{
 15     int u, v, cap, flow, cost;
 16     int nxt;
 17     Edge(int u = 0, int v = 0, int cap = 0, int flow = 0, int cost = 0, int nxt = 0) : u(u), v(v), cap(cap), flow(flow), cost(cost), nxt(nxt) {}
 18 }e[maxe << 1];
 19 int head[maxv];
 20 int cnt = 0;
 21 void init(){
 22     memset(head, -1, sizeof(head));
 23     cnt = 0;
 24 }
 25 void add(int u, int v, int cap, int flow, int cost){
 26     e[cnt] = Edge(u, v, cap, flow, cost, head[u]);
 27     head[u] = cnt++;
 28     e[cnt] = Edge(v, u, 0, flow, -cost, head[v]);
 29     head[v] = cnt++;
 30 }
 31 int mx[maxv], my[maxv], hx[maxv], hy[maxv];
 32
 33 int s, t, N;
 34 int d[maxv], p[maxv], inq[maxv], a[maxv];
 35 bool BellmandFord(int s, int t, int &flow, int &cost){
 36     for(int i = 0; i < N; i++) d[i] = inf;
 37     memset(inq, 0, sizeof inq);
 38     d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = inf;
 39     queue<int> q;
 40     q.push(s);
 41     while(!q.empty()){
 42         int u = q.front(); q.pop();
 43         inq[u] = 0;
 44         for(int i = head[u]; ~i; i = e[i].nxt){
 45             Edge &tp = e[i];
 46             if(tp.cap > tp.flow && d[tp.v] > d[u] + tp.cost){
 47                 d[tp.v] = d[u] + tp.cost;
 48                 p[tp.v] = i;
 49                 a[tp.v] = min(a[u], tp.cap - tp.flow);
 50                 if(!inq[tp.v]) {
 51                     q.push(tp.v);
 52                     inq[tp.v] = 1;
 53                 }
 54             }
 55         }
 56     }
 57     if(d[t] == inf) return false;
 58     flow += a[t];
 59     cost += d[t] * a[t];
 60     int u = t;
 61     while(u != s){
 62         e[p[u]].flow += a[t];
 63         e[p[u] ^ 1].flow -= a[t];
 64         u = e[p[u]].u;
 65     }
 66     return true;
 67 }
 68 int MCMF(){
 69     int flow = 0, cost = 0;
 70     while(BellmandFord(s, t, flow, cost)) ;
 71     return cost;
 72 }
 73
 74 int main(){
 75     //freopen("in.txt", "r", stdin);
 76     //freopen("out.txt", "w", stdout);
 77     int n, m;
 78     while(scanf("%d %d", &n, &m) && (n || m)){
 79         int cth = 0, ctm = 0;
 80
 81         init();
 82         for(int i = 0; i < n; i++) {
 83             scanf("%s", gra[i]);
 84             for(int j = 0; j < m; j++){
 85                 if(gra[i][j] == ‘H‘){
 86                     hx[cth] = i;
 87                     hy[cth++] = j;
 88                 }
 89                 if(gra[i][j] == ‘m‘){
 90                     mx[ctm] = i;
 91                     my[ctm++] = j;
 92                 }
 93             }
 94         }
 95         for(int i = 0; i < cth; i++){
 96             for(int j = 0; j < ctm; j++){
 97                 int dis = abs(hx[i] - mx[j]) + abs(hy[i] - my[j]);
 98                 add(i, cth + j, 1, 0, dis);
 99             }
100         }
101         s = cth + ctm;
102         t = s + 1;
103         N = t + 1;
104         for(int i = 0; i < cth; i++){
105             add(s, i, 1, 0, 0);
106         }
107         for(int i = 0; i < ctm; i++){
108             add(cth + i, t, 1, 0, 0);
109         }
110         int ans = MCMF();
111         printf("%d\n", ans);
112     }
113     return 0;
114 }

原文地址:https://www.cnblogs.com/yijiull/p/8318796.html

时间: 2024-11-06 12:44:35

Going Home HDU - 1533 (费用流)的相关文章

hdu 2686 费用流 / 双线程DP

题意:给一个方阵,求从左上角出到右下角(并返回到起点),经过每个点一次不重复,求最大获益(走到某处获得改点数值),下来时每次只能向右或向下,反之向上或向左. 俩种解法: 1  费用流法:思路转化:从左上角流出2的流量,(表示走俩条路),归于右下角,可以走就有边(右和下),权为负的费用,源点连起点,汇点连终点,流量为2. 除源汇外所有点一分为2,Y向X对应点有流量1的边,之前边为X到Y的(原图),这样处理解决每个点只最多走一次(除了源汇外)(X部只出,Y部要出必先回到X对应点).跑最小费用最大流即

HDU 3376 费用流 Matrix Again

咳咳,内个,内什么,白书上的费用流模板没过,后来换了种存图方式才过. 题意: 给出一个n × n的矩阵,每个格子中有一个数字代表权值,找出从左上角出发到右下角的两条不相交的路径(起点和终点除外),使得两条路径权值之和最大. 分析: 如果n比较小的话是可以DP的,但是现在n非常大,DP会超时的. 这个用费用流来求解: 因为每个点只能走一次,所以先拆点,两点之间连一条容量为1费用为对应格子权值的边,如果是起点或终点,因为要走两次,所以要连容量为2的边. 对于不同格子之间,如果能到达,连一条容量为IN

hdu 5045 费用流

滚动建图,最大费用流(每次只有就10个点的二分图).复杂度,m/n*(n^2)(n<=10),今年网络赛唯一网络流题,被队友状压DP秒了....难道网络流要逐渐退出历史舞台???.... #include<iostream> //78ms #include<cstdio> #include<queue> using namespace std; const double inf =0x3f3f3f3f; const int maxv=50,maxe=500; in

hdu 4406 费用流

这题问题就是当前时刻到底选择哪门课程,易知选择是和分数有关的,并且是一个变化的权值,所以可以用拆点的方式,把从基础分到100分都拆成点,但若这样拆点的话,跑费用流时就必须保证顺序,这样就麻烦了..观察公式,发现同一门课,分数越高,权值是越低的,所以这是一个单调的,这样的话就可以对每一个分数建一条边,费用流会一条一条的跑. 注意将课程放在X集 #include<cstdio> #include<queue> #include<algorithm> #include<

HDU 5045 费用流求最大权

点击打开链接 题意:有n个人和m到题目,每个人做对的概率以矩阵形式给出,问如何分配才可以使做对的概率最大,有一个限制条件是做到目前为止每两个人的做题数量差距不能超过1,也就是前n道题目,必须一人做一个 思路:网上都是dp多一点,用网络流也可以,不过麻烦很多,可是本弱是一点dp都不会的选手啊,只能用网络流了,对于那个限制条件,我们可以以前n道题建一次图,然后再来n个,不过就直接建完就可以了,然后我们要求的是什么呢,很明显是最大权,而最大费用最大流刚好可以解决,这里面的费用流有两种方法,用spfa找

HDU 3667 费用流 拆边 Transportation

题意: 有N个城市,M条有向道路,要从1号城市运送K个货物到N号城市. 每条有向道路<u, v>运送费用和运送量的平方成正比,系数为ai 而且每条路最多运送Ci个货物,求最小费用. 分析: 拆边,每条边拆成费用为a, 3a, 5a的边,这样就能保证每条边的费用和流量的平方成正比. 因为最多运送K个货物,所以增加一个源点和城市1连一条容量为K费用为0的边. 跑一边最小费用最大流,如果满流才有解. 1 #include <iostream> 2 #include <cstdio&

HDU 5644 (费用流)

Problem King's Pilots (HDU 5644) 题目大意 举办一次持续n天的飞行表演,第i天需要Pi个飞行员.共有m种休假计划,每个飞行员表演1次后,需要休假Si天,并提供Ti报酬来进行下一次表演.刚开始拥有k个飞行员.也可以招募飞行员来进行表演(数量无限),需要提供报酬q,在p天后参加表演.询问使表演顺利进行的最少花费,若无法进行,输出No solution. 解题分析 搬运官方题解: 稍微解释一下: 首先忽略Xi.Yi向T的流量表示第i天有多少人参加表演(第2条).S向Y1

HDU 3667 费用流(拆边)

题意:有n个城市(1~n),m条有向边:有k件货物要从1运到n,每条边最多能运c件货物,每条边有一个危险系数ai,经过这条路的费用需要ai*x2(x为货物的数量),问所有货物安全到达的费用. 思路:c<=5,这里可以做文章:把每条边拆成c条边,容量都为1,费用为ai*(2*i-1)(第二个i是指拆边时的第几条边).推导:x2-(x-1)2=2x-1. 代码: 1 #include<stdio.h> 2 #include<string.h> 3 #define min(x,y)

HDU 3435 费用流

点击打开链接 题意:给个无向的图,问你删除任意边后,使这个图是哈密顿图,若有多个,输出路径上的所有权值和最小,没有就输出NO 思路:今天开始从10年多校开始刷题,敌人留给我们的时间不多了,这题看完题意后,看了看样例,自己yy了一下,写了一发,交了ac,看了样例后我是这样想的,因为是哈密顿图,那么每个点肯定是走了两次,而图是无向图,和求最大匹配有些类似,然后就瞎YY的过了 #include <queue> #include <vector> #include <stdio.h&