4 3 3 1 1 1 1 1 1 YYN NYY YNY YNY YNY YYN YYN NNY
3
F种食物,N个人,D种饮料
先输入一排F个数字的是每种食物的量;
再输入D个数字是每种饮料的量;
然后N行 是每个人可以接受的食物是哪几种,第一个Y代表可以接受第一种食物
再N行,是每个人可以接受的饮料是哪几种,
每个人都只用给他一个食物或者饮料
做法是, 设一个超级源点beg, beg 连接到 各种食物, 权值是该食物的量.
然后把每个人拆开, 拆成 点头 和点尾,因为只吃一个,所以权值是1;
然后把这各种食物,根据每个人的爱好连接 到 人的点头,因为只吃一个,所以权值是1
在把每个人的点尾根据个人爱好,连接到 饮料,权值同理也是1;
再设一个超级汇点fin, 把各种饮料连接到 fin;
像这样建图
#include<stdio.h> #include<string.h> #include<queue> using namespace std; #define inf 1000000 #define N 1000 #define M 100000 //N为点数 M为边数 200 400 200 inline int Min(int a,int b){return a>b?b:a;} //注意这个类型是int struct Edge{ int from, to, cap, nex; }edge[M*2];//双向边,注意RE 注意这个模版是 相同起末点的边 同时有效而不是去重 int head[N],edgenum;//2个要初始化-1和0 void init() { memset(head,-1,sizeof(head)); edgenum=0; } void addedge(int u, int v, int cap){//网络流要加反向弧 Edge E = {u, v, cap, head[u]}; edge[ edgenum ] = E; head[ u ] = edgenum++; Edge E2 = {v, u, 0, head[v]}; //这里的cap若是单向边要为0 edge[ edgenum ] = E2; head[ v ] = edgenum++; } int dis[N], cur[N];//dis[i]表示i点距离起点的距离 cur[i]表示i点所连接的边中 正在考虑的边 优化不再考虑已经用过的点 初始化为head bool vis[N]; bool BFS(int Start,int End){//跑一遍最短路 memset(vis,0,sizeof(vis)); memset(dis,-1,sizeof(dis)); queue<int>Q; Q.push(Start); dis[Start]=0; vis[Start]=1; while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].nex){ Edge E = edge[i]; if( !vis[E.to] && E.cap > 0) { vis[ E.to ] = true; dis[ E.to ] = dis[ u ] + 1; if(E.to == End) return true; Q.push( E.to ); } } } return false; } int DFS(int x, int a,int End){//当前 流入x 的流量是a 流量a 是所有流过边中 边权的最小值 if( x == End || a == 0)return a; int flow = 0, f; //flow表示从x点流到下面所有点,最大的流量 for(int& i = cur[x]; i != -1; i = edge[i].nex) { Edge& E = edge[i]; if(dis[x] + 1 == dis[E.to] && (f = DFS(E.to , Min(a, E.cap), End))>0 ) { E.cap -= f; edge[ i^1 ].cap += f;//反向边要减掉 flow += f; a -= f; if(a==0)break; } } return flow; } int Maxflow(int Start,int End){ int flow=0; while(BFS(Start,End)){ //当存在源点到汇点的路径时 memcpy(cur,head,sizeof(head));//把head的数组复制过去 flow += DFS(Start, inf, End); } return flow; } int main() { int fin,beg; int i,j,f,n,d,tem; char a[300]; while(scanf("%d%d%d",&n,&f,&d)!=EOF)//f个点代表食物, 2*n个点代表人 d个点代表饮料 { init(); fin=f+2*n+d+1; beg=0; for(i=1;i<=f;i++) { scanf("%d\n",&tem); addedge(beg, i , tem); } for(i=1;i<=d;i++) { scanf("%d\n",&tem); addedge(i+f+2*n, fin, tem); } for(i=1;i<=n;i++) { scanf("%s",a); for(j=0;j<f;j++) { if(a[j]=='Y') { addedge( j+1, f+i , 1);//食物到人 } } addedge(f+i, f+i+n, 1);//人的量 } for(i=1;i<=n;i++)//人 { scanf("%s",a); for(j=0;j<d;j++) { if(a[j]=='Y') { addedge(f+i+n, f+2*n+j+1,1);//人到饮料 } } } printf("%d\n",Maxflow(beg,fin)); } return 0; }
hdu 4292 Food 最大流+拆点,布布扣,bubuko.com
原文地址:http://blog.csdn.net/u013532224/article/details/38533505