题意:国王对其N个 (1 <= N <= 400)儿子各有一个喜欢度,有N个美女,N个儿子喜欢美女中的一些,国王的幸福感 = 对可以成婚的儿子的喜欢度 ^ 2 的和,问国王最幸福时,儿子的对象情况。
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2362
——>>男、女,很像二分图吧。。
要使平方和最大,可转化为要使和最大。。
将儿子按国王对他们的喜欢度从高到低排序,再依次进行匹配对象,因为在求增广路的时候,不会使已匹配上的点丢失,所以二分图最大匹配国王幸福感最大时的匹配。。(会不会国王喜欢度高的儿子先匹配了导致后面的儿子抢不到该对象而使国王的幸福感不是最高呢?不会,因为一个美女最多只归一个儿子,如果没有增广路,那么先得到的儿子总使国王更幸福。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using std::sort;
const int MAXN = 400 + 10;
struct PERSON
{
int id;
int val;
bool operator < (const PERSON& e) const
{
return val > e.val;
}
} son[MAXN];
struct EDGE
{
int to;
int nxt;
} edge[MAXN * MAXN * 2];
bool vis[MAXN << 1];
int N;
int ecnt, hed[MAXN << 1];
int fa[MAXN << 1];
int pto[MAXN];
void Init()
{
ecnt = 0;
memset(hed, -1, sizeof(hed));
}
void AddEdge(int u, int v)
{
edge[ecnt].to = v;
edge[ecnt].nxt = hed[u];
hed[u] = ecnt++;
}
void Read()
{
int cnt, girlson;
scanf("%d", &N);
for (int i = 1; i <= N; ++i)
{
scanf("%d", &son[i].val);
son[i].id = i;
}
sort(son + 1, son + 1 + N);
for (int i = 1; i <= N; ++i)
{
pto[son[i].id] = i;
}
for (int i = 1; i <= N; ++i)
{
scanf("%d", &cnt);
for (int j = 1; j <= cnt; ++j)
{
scanf("%d", &girlson);
AddEdge(pto[i], N + girlson);
}
}
}
bool Match(int u)
{
for (int e = hed[u]; e != -1; e = edge[e].nxt)
{
int v = edge[e].to;
if (!vis[v])
{
vis[v] = true;
int temp = fa[v];
fa[v] = u;
if(temp == -1 || Match(temp)) return true;
fa[v] = temp;
}
}
return false;
}
void Solve()
{
int ret[MAXN];
memset(fa, -1, sizeof(fa));
for (int i = 1; i <= N; ++i)
{
memset(vis, 0, sizeof(vis));
Match(i);
}
memset(ret, 0, sizeof(ret));
for (int i = N + 1; i <= N + N; ++i)
{
if (fa[i] != -1)
{
ret[son[fa[i]].id] = i - N;
}
}
for (int i = 1; i < N; ++i)
{
printf("%d ", ret[i]);
}
printf("%d\n", ret[N]);
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
Init();
Read();
Solve();
}
return 0;
}