題目大意:
有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!如果還...