P1402 酒店之王 link
思路:
这道题,问最多可以使多少人满足的最大匹配,我们一般采用二分图。
考虑将房间做一遍二分图,菜做一遍二分图。
但是我们要注意一个细节,
假设编号为3的客人喜欢1号房间,1号菜
可是房间1号被占用了,而菜没有被占用
这时来了一个编号为4的客人,喜欢2号房(空),1号菜
但是你的ans并不会+1,应为find2时link2[1]=3;
也就是说一号菜被3号客人占用了;
但是3号客人并没有占用
所以我们必须还原数组!!
邻接矩阵(100分):
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e2 + 10;
struct node {int room[N], food[N];} a[N];
int n, p, q, link1[N], link2[N], ll1[N], ll2[N], ans;
bool v1[N], v2[N];
bool find1(int x)
{
for(int i = 1; i <= p; i++)
{
if(!v1[i] && a[x].room[i])
{
v1[i] = 1;
if(!link1[i] || find1(link1[i]))
{
link1[i] = x;
return 1;
}
}
}
return 0;
}
bool find2(int x)
{
for(int i = 1; i <= q; i++)
{
if(!v2[i] && a[x].food[i])
{
v2[i] = 1;
if(!link2[i] || find2(link2[i]))
{
link2[i] = x;
return 1;
}
}
}
return 0;
}
int main()
{
scanf("%d%d%d", &n, &p, &q);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= p; j++)
scanf("%d", &a[i].room[j]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= p; j++)
scanf("%d", &a[i].food[j]);
for(int i = 1; i <= n; i++)
{
memset(v1, 0, sizeof(v1));
memset(v2, 0, sizeof(v2));
for(int j = 1; j <= p; j++)
ll1[j] = link1[j];
for(int j = 1; j <= q; j++)
ll2[j] = link2[j];
if(find1(i) && find2(i)) ans++;
else
{
for(int j = 1; j <= p; j++)
link1[j] = ll1[j];
for(int j = 1; j <= q; j++)
link2[j] = ll2[j];
}
}
printf("%d\n", ans);
return 0;
}
不知道为什么,我打邻接表只得了80分,邻接矩阵却100分,望大佬斧正!
邻接表(80分):
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e2 + 10;
struct node {int room[N], food[N];} a[N];
struct EDGE {int to, next;} e[N * 2], e1[N * 2];
int n, p, q, head[N], head1[N], cnt, cnt1, link1[N], link2[N], ll1[N], ll2[N], ans;
bool v1[N], v2[N];
void add(int x, int y)
{
e[++cnt] = (EDGE){y, head[x]};
head[x] = cnt;
}
void add1(int x, int y)
{
e1[++cnt1] = (EDGE){y, head1[x]};
head1[x] = cnt1;
}
bool find1(int x)
{
for(int i = head[x]; i; i = e[i].next)
{
int v = e[i].to;
if(!v1[v])
{
v1[v] = 1;
if(!link1[v] || find1(link1[v]))
{
link1[v] = x;
return 1;
}
}
}
return 0;
}
bool find2(int x)
{
for(int i = head1[x]; i; i = e1[i].next)
{
int v = e1[i].to;
if(!v2[v])
{
v2[v] = 1;
if(!link2[v] || find2(link2[v]))
{
link2[v] = x;
return 1;
}
}
}
return 0;
}
int main()
{
scanf("%d%d%d", &n, &p, &q);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= p; j++)
{
scanf("%d", &a[i].room[j]);
if(a[i].room[j]) add(i, j);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= p; j++)
{
scanf("%d", &a[i].food[j]);
if(a[i].food[j]) add1(i, j);
}
for(int i = 1; i <= n; i++)
{
memset(v1, 0, sizeof(v1));
memset(v2, 0, sizeof(v2));
for(int j = 1; j <= p; j++)
ll1[j] = link1[j];
for(int j = 1; j <= q; j++)
ll2[j] = link2[j];
if(find1(i) && find2(i)) ans++;
else
{
for(int j = 1; j <= p; j++)
link1[j] = ll1[j];
for(int j = 1; j <= q; j++)
link2[j] = ll2[j];
}
}
printf("%d\n", ans);
return 0;
}