给出牛,饮料还有食物的数量,每头牛给出喜欢的饮料和食物,最后求出能够满足的牛的数量
看别人的算法,把牛分解成两个点,然后按照 饮料-牛1-牛1-食物的对应关系进行计算最大网络流,这样形成了多源点多汇点的最大流
如果这个点不分解的话,为什么不行?纠结...
后来想明白了,如果不把牛拆开的话,多个饮料会对应到一头牛上,并且这头牛如果再对应到另外的食物的话,也可算是增广路,但是已经不符合条件了
所以把牛拆开加一条1的路,可以限制每头牛只能对应一个饮料
先放上代码,回头思考
#include <cstdio> #include <cstdlib> #include <iostream> #include <string.h> #include <queue> #include <limits.h> #define MAX 500 using namespace std; int n,f,d; int cap[MAX][MAX]; int EKarp(int s,int t) { queue<int> Q; int a[MAX],flow[MAX][MAX],pre[MAX]; int f = 0,u,v; memset(flow,0,sizeof(flow)); while(1) { memset(a,0,sizeof(a)); a[s] = INT_MAX; Q.push(s); while( !Q.empty() ) { u = Q.front(); Q.pop(); for(v=s; v<=t; v++) if( !a[v] && cap[u][v] > flow[u][v] ) { Q.push(v); a[v] = a[u] < cap[u][v] - flow[u][v] ? a[u] : cap[u][v] - flow[u][v]; pre[v] = u; } } if( a[t] == 0 ) break; for(u=t; u!=s; u=pre[u]) { flow[pre[u]][u] += a[t]; flow[u][pre[u]] -= a[t]; } f += a[t]; } return f; } int main() { int ff,dd,ans,i; int food,drink; while( scanf("%d%d%d",&n,&f,&d) != EOF ) { memset(cap,0,sizeof(cap)); for(i=1; i<=n; i++) { scanf("%d%d",&ff,&dd); cap[i][i+n] = 1; while( ff-- ) { scanf("%d",&food); cap[2*n+food][i] = 1; } while( dd-- ) { scanf("%d",&drink); cap[i+n][2*n+f+drink] = 1; } } for(i=2*n+1; i<=2*n+f; i++) cap[0][i] = 1; for(i=2*n+f+1; i<=2*n+f+d; i++) cap[i][2*n+f+d+1] = 1; ans = EKarp(0,2*n+f+d+1); printf("%d\n",ans); } return 0; }