题意:跟POJ3281基本上一样的拆点网络流。

建图:建一超级源点和一超级汇点,源点与食物相连,边权为其数量,汇点与饮料相连,边权也为其数量,把人分成两个点,之间的边权为1。每个人与之需要的食物和饮料相连,边权为1。

代码(SAP模板):

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <queue>
  6 using namespace std;
  7 const int maxn=101050;
  8 const int maxm=3000000;
  9 const int oo=1<<30;
 10 int idx,N,F,D;
 11 int cur[maxn],pre[maxn];
 12 int dis[maxn],gap[maxn];
 13 int aug[maxn],head[maxn];
 14 struct Node
 15 {
 16     int u, v, w;
 17     int next;
 18 }edge[maxm];
 19 void addEdge(int u, int v, int w)
 20 {
 21     edge[idx].u=u;
 22     edge[idx].v=v;
 23     edge[idx].w=w;
 24     edge[idx].next=head[u];
 25     head[u]=idx++;
 26     edge[idx].u=v;
 27     edge[idx].v=u;
 28     edge[idx].w=0;
 29     edge[idx].next=head[v];
 30     head[v]=idx++;
 31 }
 32 int SAP(int s,int e,int n)
 33 {
 34     int max_flow=0,v,u=s;
 35     int id,mindis;
 36     aug[s]=oo;
 37     pre[s]=-1;
 38     memset(dis,0,sizeof(dis));
 39     memset(gap,0,sizeof(gap));
 40     gap[0] = n;
 41     for (int i=0;i<=n;i++)
 42     {
 43         cur[i]=head[i];
 44     }
 45     while(dis[s]<n)
 46     {
 47         bool flag=false;
 48         if(u==e)
 49         {
 50             max_flow+=aug[e];
 51             for (v=pre[e];v!=-1;v=pre[v])
 52             {
 53                 id = cur[v];
 54                 edge[id].w-=aug[e];
 55                 edge[id^1].w+=aug[e];
 56                 aug[v]-=aug[e];
 57                 if (edge[id].w==0)
 58                 u=v;
 59             }
 60         }
 61         for(id=cur[u];id!=-1;id=edge[id].next)
 62         {
 63             v=edge[id].v;
 64             if(edge[id].w>0&&dis[u]==dis[v]+1)
 65             {
 66                 flag=true;
 67                 pre[v]=u;
 68                 cur[u]=id;
 69                 aug[v]=min(aug[u], edge[id].w);
 70                 u=v;
 71                 break;
 72             }
 73         }
 74         if (flag==false)
 75         {
 76             if(--gap[dis[u]]==0)
 77             break;
 78             mindis=n;
 79             cur[u]=head[u];
 80             for(id=head[u];id!=-1;id=edge[id].next)
 81             {
 82                 v=edge[id].v;
 83                 if(edge[id].w>0&&dis[v]<mindis)
 84                 {
 85                     mindis=dis[v];
 86                     cur[u]=id;
 87                 }
 88             }
 89             dis[u]=mindis+1;
 90             gap[dis[u]]++;
 91             if(u!=s)
 92             u=pre[u];
 93         }
 94     }
 95     return max_flow;
 96 }
 97 int main()
 98 {
 99     while(~scanf("%d%d%d",&N,&F,&D))
100     {
101         int source=0,sink=N+N+F+D+10;
102         memset(head,-1,sizeof(head));
103         idx=0;
104         int a,b,f,d;
105         int food [10000];
106         int drink[10000];
107         char str[500][500];
108         for(int i=1;i<=F;i++)
109         {
110             scanf("%d",&food[i]);
111             addEdge(source,i,food[i]);
112         }
113         for(int i=1;i<=D;i++)
114         {
115             scanf("%d",&drink[i]);
116             addEdge(i+F,sink,drink[i]);
117         }
118         for(int i=1;i<=N;i++)
119         {
120             addEdge(D+F+i,D+F+N+i,1);
121         }
122         for(int i=1;i<=N;i++)
123         {
124             scanf("%s",str[i]+1);
125             for(int j=1;j<=F;j++)
126             {
127                 if(str[i][j]=='Y')
128                 {
129                     addEdge(j,F+D+i,1);
130                 }
131             }
132         }
133 
134         for(int i=1;i<=N;i++)
135         {
136             scanf("%s",str[i]+1);
137             for(int j=1;j<=D;j++)
138             {
139                 if(str[i][j]=='Y')
140                 {
141                     addEdge(F+D+N+i,F+j,1);
142                 }
143             }
144         }
145         int n=sink+1;
146         printf("%d\n",SAP(source,sink,n));
147     }
148     return 0;
149 }
posted on 2012-09-26 12:00  pony1993  阅读(351)  评论(0编辑  收藏  举报

View My Stats