poj3281 dining 經典最大流建模方法

2021-07-04 16:00:52 字數 1328 閱讀 1175

題意:有f中食物和d種飲料,每頭牛只能享用一種食物和飲料,每個食物跟飲料也只能被一頭牛享用。現在有n頭牛,每頭牛都有自己喜歡的食物種類列表和飲料列表,問最多能使幾頭牛同時享用到自己喜歡的食物和飲料。f,d,n都是一百以內的。

思路:就不說一開始的想法了,是最近學習的最大流的建模裡面的新的方法。

之前做過幾道題,比如poj2391這道,它是比較一般的左邊一些點代表著**,2391這道題就是每個點的牛的數量,右邊乙個點集代表了需求並與匯點連線,這道題就是每個點能容納的牛數,然後拆點聯一下套模板就好了。

而現在這道題跟2391這道有點相似,那我們就可以把食物當作**,經過牛這些點,然後走到代表飲料的需求的點。

我個人認為也可以這麼理解吧,每乙個食物從源點出來,然後經過飲料進入匯點才能組成一對,然後中間必須經過喜歡它們的牛。

但是有乙個問題就是如果單純的食物-》牛-》飲料,那麼就會出現多對食物與飲料被乙個牛享用的情況,所以把牛拆了,變成食物->牛->牛->飲料,其中這兩個牛是同乙個,邊的容量都是1,這麼的話就會避免,乙個牛享用多對的情況了,因為牛->牛的容量是1。

至於模板,dinic與sap都行,速度差不多,有些情況下貌似sap稍快些。

**:

#include#include#include#include#includeusing namespace std;

const int maxn=50000;

struct node

;node edge[maxn<<1];

int head[500];

int cnt;

int dis[500];

int m,n;

int ans;

void init()

void add(int a,int b,int c)

int bfs()// 給各點分層,離源點的遠近分}}

if(dis[m] < 0)

return 0;

return 1;

}int find(int x,int low) //找增廣

}return 0;

}void dinic()

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

}int main()

//源點指向食物

for(i=1; i<=d; i++)

//飲料指向匯點

for(i=1; i<=n; i++)

//點的順序,食物,奶牛,飲料

for(i=1; i<=n; i++)

for(j=1; j<=d_sum; j++)

}m=sink;

dinic();

}return 0;

}

Poj 3281 Dining 拆點網路流

題意和思路都和我部落格的這篇文章幾乎一樣 這裡有一組測試資料 include include include using namespace std const int inf 0x6fffffff 權值上限 const int maxpt 450 頂點數上限 const int maxeg 450...

poj 3281Dining(網路流 拆點)

題目大意 john養了n只奶牛,他為奶牛準備了f個食物和d個飲料,但是每只奶牛只對其中的一些飲料和食物感興趣,現在請制定一些方案,使得盡可能多的奶牛吃到自己感興趣的食物和飲料,求出最多滿足奶牛的個數。思路 拆點建圖跑dinic演算法最大流,每只奶牛拆成兩個點,例如第ni個奶牛拆為ni 和 ni ni...

POJ 3281 Dining 最大流 拆點

解題思路 令st 0為源點,en f 2 n 1為匯點,st向每種食物建流量為1的邊,每種食物向喜歡它的牛 拆點1 建流量為1的邊,眉頭牛的拆點之間建流量為1的邊,每頭牛 拆點2 向它喜歡的飲料建流量為1的邊,每種飲料向en建流量為一的邊。注意,一定要將牛拆點,如果一頭牛只用乙個點然後連線飲料和食物...