HDU4292 FOOD 最大流 拆點

2021-08-20 12:55:24 字數 1774 閱讀 2717

題目大意:

有n個人,num1種食物,num2種飲料。每種食物和每種飲料是有限的。每個人有自己喜歡的食物和飲料的種類。問最多有多少人選到自己喜歡的食物和飲料的搭配方案。

每個人只能選乙個食物和一杯飲料

這是一道最大流專題裡的題目。拿到題很容易想到這一種建圖方式。

超級源點s向每種食物連邊,流量為該種食物的數量。

每種飲料向超級匯點t連邊,流量為該種飲料的數量。

每個人向自己喜歡的飲料和食物連邊,流量為1。

一開始肯定會有這種建圖的想法。但是這樣還不夠。

題目說了,每個人只能選一杯飲料和乙個食物。這樣建圖很明顯不能保證每個人只選了一杯飲料和乙個食物。還有問題。

舉個栗子:

只有乙個人,他喜歡3種食物,3種飲料。每種食物和飲料的數量為1.

把這個圖跑一邊最大流你會發現你得到的答案是3,而不是1!

為什麼呢?因為你沒處理每個人只能選乙個食物和飲料的限制條件。

把每個人拆成兩個點,不妨稱作左點 i 和右點i + n。左點和右點連邊,流量設為1.

重新建圖:

每種食物向喜歡它的人的左點 i 連邊,流量為1.

每個人的右點 i + n 向他喜歡的飲料連邊,流量為1.

然後跑最大流就okey了。

這樣新圖就建好了。這就是網路流中的一種常用技巧:拆點

處理有限制條件的圖的時候經常使用 !

//c++ 202ms

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int mx=805;

char ar[mx];

int s,t,e,fr[mx],h[mx],nh[mx];

ll ans;

int n,num1,num2;

const ll inf=1e17;

inline

int rd()

struct lpa[mx*1000];

void ins(int f,int t,ll w)

ll min(ll x,ll y)

}if (!(--nh[h[u]])) h[t]=t;

++nh[++h[u]];

return fl-res;

}int main()

for(int i=0;iscanf("%d",&x);

ins(2*n+i+2+num1,t,x);

}for(int i=0;iscanf("%s",ar);

for(int j=0;jif(ar[j]=='y')ins(2*n+j+2,i+2,1);}}

for(int i=0;iscanf("%s",ar);

for(int j=0;jif(ar[j]=='y')ins(i+2+n,2*n+j+2+num1,1);}}

nh[0]=t;

while (h[t]!=t)

printf("%lld\n",ans);

}return

0;}

ovo

HDU 4292Food 最大流 拆點

題意就是每個人都有喜歡的飲料和食物,但是這些飲料和食物有限,問你如何選才能使最多的人喝到自己喜歡的飲料和食物。這題主要就是想清楚如何建邊,然後跑乙個最大流就好了 分別建立 源點指向飲料的邊 飲料指向人的邊 人指向自己的邊 保證每個人只被走一次 人指向食物的邊,食物指向匯點的邊。這裡要把人的點拆成兩個...

hdu4292Food(最大流Dinic演算法)

題意 每乙個人都有喜歡的吃的和喝的,每乙個人只選擇乙個數量的吃的和乙個數量的喝的,問能滿足最多的人數!思路 建圖很是重要!f food,p people,d drink 建圖 0 源點 f p p d t 匯點 將人拆分很是重要,因為每乙個人最多只能有一種選擇,也就是p p 的最大流量是 1!如果還...

hdu4292Food(最大流Dinic演算法)

題意 每乙個人都有喜歡的吃的和喝的,每乙個人只選擇乙個數量的吃的和乙個數量的喝的,問能滿足最多的人數!思路 建圖很是重要!f food,p people,d drink 建圖 0 源點 f p p d t 匯點 將人拆分很是重要,因為每乙個人最多只能有一種選擇,也就是p p 的最大流量是 1!如果還...