網路流之最小費用最大流之 D
題目連結
建圖:
源點到人的費用為0容量為1;
每個人到每個房子建一條邊,費用為這個房子到這個人的距離,容量為1;
房子到終點的費用為0容量為1;
做這個題時,找了半天bug,首先注意房子和人的個數不是n,誤以為n,調錯了好久,還有sum,num的初始化,一開始放錯位置了,還有就是存房子和人的位置時,存錯了;
程式碼:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define M 1100
const int inf=0x3f3f3f3f;
int n,m;
struct node
{
int u,v,c,f,next; //C為花費,F為flow流量
} e[M*40];
struct point
{
int x,y;
} a[500],b[500];
int pre[M],dis[M],head[M],t;
int vis[M];
char mmap[500][500];
void add1(int u,int v,int c,int f)
{
e[t].u=u;
e[t].v=v;
e[t].c=c;
e[t].f=f;
e[t].next=head[u];
head[u]=t++;
}
void add(int u,int v,int c,int f)//費用,流量
{
add1(u,v,c,f);
add1(v,u,-c,0); //反向邊流量初始為零,如果走反向邊費用正好和原邊抵消
}
int spfa(int s,int t)
{
int i,u,v;
queue<int>q;
q.push(s);
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
for(i=s; i<=t; i++)
dis[i]=inf;
dis[s]=0 ;
while(!q.empty())
{
u=q.front();
q.pop();
for(i=head[u]; i!=-1; i=e[i].next)
{
v=e[i].v;
if(e[i].f&&dis[v]>dis[u]+e[i].c) //找到一條最小費用流
{
dis[v]=dis[u]+e[i].c;
pre[v]=i; //記錄路徑
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
vis[u]=0;
}
if(dis[t]!=inf)
return 1;
return 0;
}
void solve(int s,int t)
{
int ans=0,i,j;
int flow=0,cost=0; //總流量、總費用
while(spfa(s,t))
{
int minf=inf;
for(i=pre[t]; i!=-1; i=pre[e[i].u])
{
if(e[i].f<minf)
minf=e[i].f;
}
flow+=minf; //該條路徑的流量
for(i=pre[t]; i!=-1; i=pre[e[i].u])
{
j=i^1;
e[i].f-=minf;
e[j].f+=minf;
}
cost+=dis[t]*minf; //單位運費和乘以流量得費用
}
printf("%d\n",cost);
}
int main()
{
while(~scanf("%d%d",&n,&m)&&(n||m))
{
t=0;
int sum=1,num=1;
memset(head,-1,sizeof(head));
for(int i=1; i<=n; i++)
{
scanf("%s",mmap[i]+1);
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// {
// printf("%c",mmap[i][j]);
// }
// printf("\n");
// }
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
if(mmap[i][j]=='m')
{
a[sum].x=i;
a[sum].y=j;
sum++;
}
if(mmap[i][j]=='H')
{
b[num].x=i;
b[num].y=j;
num++;
}
}
}
int s=0,tt=sum-1+num-1+1;
for(int i=1; i<sum; i++) //i,人,j+n,房子
{
for(int j=1; j<num; j++)
{
int dis=abs(a[i].x-b[j].x)+abs(a[i].y-b[j].y);
add(i,j+sum-1,dis,1);
}
}
for(int i=1; i<sum; i++)
{
add(s,i,0,1);
}
for(int i=1; i<num; i++)
{
add(i+sum-1,tt,0,1);
}
solve(s,tt);
}
}
相關推薦
網路流之最小費用最大流
具體思路:建好圖之後,每一次從源點到匯點走最短路,如果能走到就加上,如果走不到就停止。具體注意細節在程式碼中解釋。 AC程式碼: #include<iostream> #include<string> #include<cstring&g
網路流之最小費用最大流之 D
題目連結 建圖: 源點到人的費用為0容量為1; 每個人到每個房子建一條邊,費用為這個房子到這個人的距離,容量為1; 房子到終點的費用為0容量為1; 做這個題時,找了半天bug,首先注意房子和人的個數不是n,誤以為n,調錯了好久,還有sum,num的初始
POJ2516 Minimum Cost(網路流,最小費用最大流)
題目連結:http://poj.org/problem?id=2516 這道題有點嘔。 題目大概意思: 現在有n個店主,m個供應商,k個商品。 現在給你n*k的矩陣,表示每個店主對於每個商品的需求量。 然後給你m*k的矩陣,表示每個供應商每個物品的擁有量。 然後給你k個n
[ZJOI2010]網路擴容,P2604,最小費用最大流
正題 這一題想了我很久,結果發現很智障。 原來是一個裸題啊。 先跑最大流,然後剩下的是一個殘餘網路,容易知道如果擴容,肯定在殘餘網路裡面找路徑,因為如果不在殘
洛谷 ~ P2604 [ZJOI2010] ~ 網路擴容 (最小費用最大流)
第一問:建邊u->v容量為題中容量,花費為0,跑費用流得到的最大流就是答案。 第二問:建邊u->v容量為INF,花費題中花費,跑費用流得到的費用就是答案。 #include<bits/stdc++.h> using namespace std
計蒜客 ICPC焦作網路賽 Modular Production Line(區間k覆蓋 + 最小費用最大流)
大致題意:給你N個機器,可以生產M個物品,每個物品i生產出來需要區間[li,ri]內的機器一起工作。可以產生wi的利潤。每個物品只能生產一次,每個機器最多隻能工作k次,現在問你能夠產生的最大利潤。 每個機器只能工作k次,每個物品只能夠生產一次,求最大
【網路流24題】餐巾計劃(最小費用最大流)
題意 一個餐廳在相繼的 nnn 天裡,每天需用的餐巾數不盡相同。假設第 iii 天需要 rir_iri 塊餐巾。餐廳可以購買新的餐巾,每塊餐巾的費用為 PPP 分;或者把舊餐巾送到快洗部,洗一塊需 MMM天,其費用為 FFF 分;或者送到慢洗部,洗一塊需
【網路流24題】運輸問題(最小費用最大流)
題意 W 公司有 mmm 個倉庫和 nnn 個零售商店。第 iii 個倉庫有 aia_iai 個單位的貨物;第 jjj 個零售商店需要 bjb_jbj 個單位的貨物。貨物供需平衡,即∑i=1mai=∑j=1nbj\sum\limits_{i =
A Birthday 網路流最小費用最大流
題目連結 題意:n只蠟燭,m個區域,第i個蠟燭可以放在第或者區域裡,每個區域所耗時間等於佔用該區域蠟燭個數的平方。求總的最小消耗時間。 思路:可以看成每個蠟燭可以流向兩個區域,建立兩個容量為1,費用為0的邊,建一個源點與n個蠟燭連邊,容量為1,費用為0,再建一個匯點讓m個
網路流(2)-----最小費用最大流
一. 二. 1.EK演算法 + SPFA 最短路 (1)程式碼: #include <iostream> #include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f c
【網路流24題】 No.10 餐巾計劃問題 (線性規劃網路優化 最小費用最大流)
【題意】 一個餐廳在相繼的 N 天裡, 每天需用的餐巾數不盡相同。 假設第 i 天需要 ri 塊餐巾(i=1,2,…, N)。 餐廳可以購買新的餐巾,每塊餐巾的費用為 p 分;或者把舊餐巾送到快洗部,洗一塊需 m 天,其費用為 f分;或者送到慢洗部, 洗一塊需 n 天(n>m),其費用為 s<
2135 Farm Tour (網路流-最小費用最大流)
題目連結 題意:給出1~n點和m條無向邊,要求從1走到n再從n回到1處的最小費用,要求每條邊走過不超過1次 題解:可轉換為求從1到n的流量f=2的最小費用流問題(不可先從左到右掃一遍最短路再刪去使用過的邊最後再次最短路回起點,只做到區域性最優而非全域性)最小費用最大流(D
[網路流24題] 18 分配問題(二分圖最佳匹配,最小費用最大流)
題目大意: 有n個工作要分配給n個人做,給出每個人做每件工作所產生的效益, 求出最小總效益和最大總效益; 思路分析: 這道題 和17題的思路是一樣的; ①:設立一個源點s,從s向每個人連一條邊,容量為1, 費用為0; ②:從每個人向每個工作連一條邊,容量為INF,費用為這個
LOJ 2321 清華集訓2017 無限之環 拆點+最小費用最大流
題面:中文題面,這裡不佔用篇幅 分析: 看到題面,我就想棄療…… 但是作為任務題單,還是抄了題解…… 大概就是將每個格子拆點,拆成五個點,上下左右的觸點和一個負責連源匯點的點(以下簡稱本點)。 這個這個本點要根據初始形態向相應的觸點連線費用為0容量為1的邊,再由旋轉規
計蒜客-2017 ACM-ICPC 亞洲區(烏魯木齊賽區)網路賽J題Our Journey of Dalian Ends (最小費用最大流)
題意: 給定若干個城市,出發點為大連,目的地為西安,但是要求中途必須經過上海,並且圖中每個城市只能經過一次,給出m條路(雙向道路),走第i條路需要wi代價,求所有滿足要求的方案中花費的最小代價,如果沒有滿足的方案,輸出-1。 思路: 相當於求從大連到上海加上西安到上海花費的
網路流——最小費用最大流
前言 Q:為什麼突然想搞網路流? A:迫於Tham_蛤mu的淫威 演算法過程 用最短路演算法求出s->t的路徑(把路徑要摳出來,而且每條邊要有容量) 算一下路徑裡面的可以流過的最大的流量 發現此時的花費就是\(dis_t*Flow\),累加即可. 重複1->3直到不能夠到達
【洛谷4016】 負載平衡問題(網路流24題,最小費用最大流)
前言 網路流24題還是要寫一下。 Solution 我們先來研究一下這個題目是個什麼東西: 每一個點有可能比平均數多,也有可能少,然後你就發現相當於是我們建了兩個超級源點和超級匯點,然後從這兩個點去分和流入。 然後對於這個環就可以直接建環(注意建邊的時候的一些細節操作) 跑一邊費用流就好了。 #inc
【網路流】最小費用最大流(模板)
#include <bits/stdc++.h> using namespace std; const int Max=50010; const int inf=1e9; int n,m,ans1,ans2,size=1,head,tail,s,t; int f
網路流學習(最小費用最大流)
知道了最大流之後這個沒什麼難度 但是好像全世界都是用的EK演算法(SPFA),要麼就來個Dijkstra 好像是說可以證明Dinic跑費用流並沒有優化,而且EK演算法在費用流裡更容易碼也更容易理解...... 於是乎luogu模板最小費用最大流 code 換了一種存反邊的方式...... 話不多說 #incl
2017 ACM-ICPC 亞洲區(烏魯木齊賽區)網路賽 J.Our Journey of Dalian Ends【最小費用最大流】
Life is a journey, and the road we travel has twists and turns, which sometimes lead us to unexpected places and unexpected people. Now our journey of Dal