P2055 [ZJOI2009]假期的宿舍
Posted garen-wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2055 [ZJOI2009]假期的宿舍相关的知识,希望对你有一定的参考价值。
有点烧脑。。。
这道题是求二分图完美匹配。没看请题意还不知道是求完美匹配,结果爆零。
人一共分三种:
在校学生 && 回家。这类人拥有一个床,但是不睡。
在校学生 && 不回家。这类人拥有一个床,但也要睡一个床。有时不一定睡自己的。
外来学生。这类人没床却想睡觉。
显然要用(2n)的空间来建立人和床。
等待匹配的人只有1、3两种情况,等待匹配的床只有1、2两种情况。
第1种情况连床没什么卵用。又不睡。
只有第2种情况的人可以连自己的床。
第3种情况的人一定要睡别人的床。
在2、3种情况中,只要认识的人有床,就可以连接。
然后套个二分图匹配的样子,跑跑网络流就ok了。
最后判断答案是不是等于人数,输出那两个表情即可。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
const int maxn = 1005, INF = 19260817;
struct Edges
{
int next, to, weight;
} e[1000005];
int head[maxn], tot;// remember to set tot = 1
int n, s, t;
bool in_school[maxn], go_home[maxn];
int dep[maxn], cur[maxn];
void link(int u, int v, int w)
{
e[++tot] = (Edges){head[u], v, w};
head[u] = tot;
}
void addEdges(int u, int v, int w)
{
link(u, v, w); link(v, u, 0);
}
int read()
{
int ans = 0; char ch = getchar();
while(ch > ‘9‘ || ch < ‘0‘) ch = getchar();
while(ch >= ‘0‘ && ch <= ‘9‘)
{
ans = ans * 10 + ch - ‘0‘;
ch = getchar();
}
return ans;
}
bool bfs()
{
memset(dep, 0, sizeof(dep));
std::queue<int> q;
dep[s] = 1; q.push(s);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = head[u]; i; i = e[i].next)
{
int v = e[i].to;
if(!dep[v] && e[i].weight > 0)
{
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[t];
}
int dfs(int u, int flow)
{
if(u == t) return flow;
for(int &i = cur[u]; i; i = e[i].next)
{
int v = e[i].to;
if(dep[v] == dep[u] + 1 && e[i].weight > 0)
{
int di = dfs(v, std::min(e[i].weight, flow));
if(di > 0)
{
e[i].weight -= di;
e[i ^ 1].weight += di;
return di;
}
}
}
return 0;
}
int dinic()
{
int ans = 0;
while(bfs())
{
for(int i = 1; i <= t; i++) cur[i] = head[i];
while(int temp = dfs(s, INF)) ans += temp;
}
return ans;
}
int main()
{
int T = read();
while(T--)
{
// how to define nodes?
// [1, n] person
// [n + 1, n + n] beds
// not go home->need bed
// only do in-school students have beds
// not in-school students->the persons visiting
// go home->never consider them
tot = 1; memset(head, 0, sizeof(head)); memset(e, 0, sizeof(e));
n = read();
int cnt = 0;
s = n + n + 1; t = s + 1;
for(int i = 1; i <= n; i++) in_school[i] = read();
for(int i = 1; i <= n; i++) go_home[i] = read();
for(int i = 1; i <= n; i++)
{
addEdges(s, i, 1);
addEdges(n + i, t, 1);
if((in_school[i] && !go_home[i]) || !in_school[i]) cnt++;
}
for(int i = 1; i <= n; i++)
{
if(in_school[i] && !go_home[i]) addEdges(i, n + i, 1);
for(int j = 1; j <= n; j++)
{
int temp = read();
if(temp && in_school[j] && !(in_school[i] && go_home[i])) addEdges(i, n + j, 1);
}
}
int ans = dinic();
if(ans == cnt) printf("^_^
");
else printf("T_T
");
}
return 0;
}
以上是关于P2055 [ZJOI2009]假期的宿舍的主要内容,如果未能解决你的问题,请参考以下文章
P2055 [ZJOI2009]假期的宿舍(二分图&最大流)