POJ 3281_Dining
題意:
FJ準備了F種食物和D種飲料,每頭牛都有喜歡的食物和飲料,并且每頭牛都只能分配一種食物和飲料。問如何分配使得同時得到喜歡的食物和飲料的牛數量最多。
分析:
首先想到將牛與其對應的食物和飲料匹配起來,即在食物、飲料與牛之間連一條邊,再在s和所有食物之間、t和所有飲料之間連一條邊。這樣每一條路徑都對應著食物飲料和牛之間的匹配方案。那么如何避免一頭牛被分配多組匹配呢?就將一頭牛拆成兩個結點,并用一條容量為1的邊連接起來,這樣求出構成的圖中的最大流,即得解。這里使用的是Dinic算法。
代碼:
#include<cstdio> #include<vector> #include<cstring> #include<queue> using namespace std; struct edge{int to, cap, rev;}; const int maxn = 105, maxm = 2000055, INF = 0x3fffffff; int d[maxm], iter[maxm]; int s, t; vector<edge>G[maxm]; int dr[maxn][maxn], f[maxn][maxn]; void add_edge(int from, int to, int cap) {G[from].push_back((edge){to, cap, G[to].size()});G[to].push_back((edge){from, 0, G[from].size()-1}); } void bfs() {memset(d, -1, sizeof(d));queue<int>q;d[s] = 0;q.push(s);while(!q.empty()){int v = q.front();q.pop();for(int i = 0; i <G[v].size(); i++){edge &e = G[v][i];if(e.cap>0&&d[e.to]<0){d[e.to] = d[v] + 1;q.push(e.to);}}} } int dfs(int v, int f) {if(v==t) return f;for(int &i = iter[v]; i < G[v].size(); i++){edge &e = G[v][i];if(e.cap > 0 && d[v] < d[e.to]){int tf = dfs(e.to, min(f, e.cap));if(tf > 0){e.cap -= tf;G[e.to][e.rev].cap +=tf;return tf;}}}return 0; } int max_flow() {int flow = 0;for(;;){bfs();if(d[t]<0) return flow;memset(iter, 0, sizeof(iter));int f;while((f = dfs(s, INF))>0){flow += f;}} } int main (void) {int N, F, D;scanf("%d%d%d",&N, &F, &D);int a, b;s = 2 * N + F + D + 1, t = s + 1;for(int i = 1; i <= N; i++){scanf("%d%d",&a, &b);add_edge(i, N + i, 1);for(int j = 0; j < a; j++){scanf("%d",&f[i][j]);add_edge(2 * N + f[i][j], i, 1);}for(int j = 0; j < b; j++){scanf("%d",&dr[i][j]);add_edge(N + i, 2 * N + F + dr[i][j], 1);}}for(int i = 1; i <= F; i++)add_edge(s, 2 * N + i, 1);for(int i = 1; i <= D; i++)add_edge(2 * N + F + i, t, 1);printf("%d\n",max_flow()); }增廣路徑必須滿足的性質
1.有奇數條邊。
2.起點在二分圖的左半邊,終點在右半邊。
3.路徑上的點一定是一個在左半邊,一個在右半邊,交替出現。(其實二分圖的性質就決定了這一點,因為二分圖同一邊的點之間沒有邊相連,不要忘記哦。)
4.整條路徑上沒有重復的點。
5.起點和終點都是目前還沒有配對的點,而其它所有點都是已經配好對的。
6.路徑上的所有第奇數條邊都不在原匹配中,所有第偶數條邊都出現在原匹配中。
7.最后,也是最重要的一條,把增廣路徑上的所有第奇數條邊加入到原匹配中去,并把增廣路徑中的所有第偶數條邊從原匹配中刪除(這個操作稱為增廣路徑的取反),則新的匹配數就比原匹配數增加了1個(奇數=偶數+1)。
轉載于:https://www.cnblogs.com/Tuesdayzz/p/5758773.html
總結
以上是生活随笔為你收集整理的POJ 3281_Dining的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flash和JavaScript通信
- 下一篇: 自定义cell