和poj3281比较像,都是一份食物加一份水匹配一个人的问题,可是这次成都的网选题数据严的多,再用邻接矩阵加EK算法就会各种超时~~
把图用邻接表建,然后用SAP找增广路即可a掉这道题。
悲剧的我在这题wa了无数次,只因为建图的时候邻接表编号从0开始,和head初始化的值重复了。
以后建邻接表一定要初始化-1,编号从2开始,又不缺那点空间~~
有图有真相,牢记错误,以免再犯:
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<climits>
#include<algorithm>
//#define min(a,b) (a<b?a:b)
#define MAXN 810
using namespace std;
int N, ff, dd, cnt, source, tink;
typedef struct
{
int from, to, cap, op;
int next;
}Node;
Node node[MAXN*MAXN];
int pre[MAXN];
int head[MAXN];
int dis[MAXN];
int num[MAXN];
int food[210];
int drink[210];
char s[210];
void init()
{
cnt = 0;
memset(node, 0, sizeof(node));
memset(head, -1, sizeof(head));
source = 0;
tink = 2*N+ff+dd+1;
}
int dfs(int x, int flow)
{
if(x == tink)
return flow;
int f = 0, mind = tink;
for(int t = head[x]; t != -1; t = node[t].next)
{
if(node[t].cap)
{
if(dis[x] == dis[node[t].to] + 1)
{
int temp = dfs(node[t].to, min(flow-f, node[t].cap));
node[t].cap -= temp;
node[node[t].op].cap += temp;
f += temp;
if(dis[source] >= tink+1)
return f;
if(flow == f)
break;
}
mind = min(mind, dis[ node[t].to ]);
}
}
if(!f)
{
if(!(--num[dis[x]]))
dis[source] = tink+1;
++num[dis[x] = mind + 1];
}
return f;
}
int SAP()
{
int ans = 0;
memset(dis, 0, sizeof(dis));
memset(num, 0, sizeof(num));
num[0] = 2*N + ff + dd + 2;
while(dis[source] < 2*N+ff+dd+2)
ans += dfs(source, INT_MAX);
return ans;
}
void Add(int u, int v, int cap)
{
node[cnt].from = u;
node[cnt].to = v;
node[cnt].cap = cap;
node[cnt].op = cnt + 1;
node[cnt].next = head[u];
head[u] = cnt++;
node[cnt].from = v;
node[cnt].to = u;
node[cnt].cap = 0;
node[cnt].op = cnt - 1;
node[cnt].next = head[v];
head[v] = cnt++;
}
int main()
{
int i, j;
while(scanf("%d%d%d", &N, &ff, &dd) != EOF)
{
init();
for(i = 1; i <= ff; i++)
{
scanf("%d", &food[i]);
}
for(i = 1; i <= dd; i++)
{
scanf("%d", &drink[i]);
}
for(i = 1; i <= N; i++)
{
scanf("%s", s);
for(j = 1; j <= ff; j++)
{
if(s[j-1] == 'Y')
{
Add(2*N+j, i, 1);
}
}
}
for(i = 1; i <= N; i++)
{
scanf("%s", s);
for(j = 1; j <= dd; j++)
{
if(s[j-1] == 'Y')
{
Add(i+N, 2*N+j+ff, 1);
}
}
}
for(i = 1; i <= N; i++)
{
Add(i, i+N, 1);
}
for(i = 1; i <= ff; i++)
{
Add(0, 2*N+i, food[i]);
}
for(i = 1; i <= dd; i++)
{
Add(2*N+ff+i, 2*N+ff+dd+1, drink[i]);
}
/*for(i = 1; i < cnt; i++)
{
cout << node[i].from << " "<<node[i].to << endl;
}*/
printf("%d\n", SAP());
}
return 0;
}