您的位置:首页 > 产品设计 > UI/UE

POJ 1904 King's Quest

2009-11-28 15:57 316 查看
King's Quest

Time Limit: 15000MSMemory Limit: 65536K
Total Submissions: 2957Accepted: 993
Case Time Limit:
2000MS
Description
Once upon a time there lived a king and he had N sons.
And there were N beautiful girls in the kingdom and the king knew about each of
his sons which of those girls he did like. The sons of the king were young and
light-headed, so it was possible for one son to like several girls.

So
the king asked his wizard to find for each of his sons the girl he liked, so
that he could marry her. And the king's wizard did it -- for each son the girl
that he could marry was chosen, so that he liked this girl and, of course, each
beautiful girl had to marry only one of the king's sons.

However, the
king looked at the list and said: "I like the list you have made, but I am not
completely satisfied. For each son I would like to know all the girls that he
can marry. Of course, after he marries any of those girls, for each other son
you must still be able to choose the girl he likes to marry."

The
problem the king wanted the wizard to solve had become too hard for him. You
must save wizard's head by solving this problem.
Input
The first line of the input contains N -- the number
of king's sons (1 <= N <= 2000). Next N lines for each of king's sons
contain the list of the girls he likes: first Ki -- the number of those girls,
and then Ki different integer numbers, ranging from 1 to N denoting the girls.
The sum of all Ki does not exceed 200000.

The last line of the case
contains the original list the wizard had made -- N different integer numbers:
for each son the number of the girl he would marry in compliance with this list.
It is guaranteed that the list is correct, that is, each son likes the girl he
must marry according to this list.

Output
Output N lines.For each king's son first print Li --
the number of different girls he likes and can marry so that after his marriage
it is possible to marry each of the other king's sons. After that print Li
different integer numbers denoting those girls, in ascending order.
Sample Input
4
2 1 2
2 1 2
2 2 3
2 3 4
1 2 3 4

Sample Output
2 1 2
2 1 2
1 3
1 4

Hint
This problem has huge input and output data,use
scanf() and printf() instead of cin and cout to read data to avoid time limit
exceed.
Source
Northeastern
Europe 2003

/*
(1)一开始以为是二分图的最大匹配,于是就是一个个尝试将每个女孩在原始匹配中的前驱改为当前喜欢这个女孩
的男孩,然后看能否为那个"被甩"的男孩找到增广路径,如果找得到,那么喜欢这个女孩的男孩就可以将这个女
孩记为自己的可行方案.这么做理论上是可行的,但是复杂度比较高,应为匈牙利算法的时间复杂度是O(n ^ 3),
加上要为每个女孩执行一次,所以最终的时间复杂度是O(n ^ 4),所以超时是必然.
(2)后来看了Discuss的讨论,可以扩展到求强连通分量.那么可以这样建图:如果1-sonN,作为图中男孩的结点,sonN + 1
- sonN + sonN作为图中女孩的结点,如果男孩i喜欢女孩j则ij之间连一条有向边,另外对于原始匹配i,j j与i之间连
一条有向边.这样对新图求强连通分量,对于某个强连通分量中的所有男孩i以及女孩j,如果i喜欢j,则j作为i的可行方案
(3)为什么强连通分量映射到可行方案呢?因为这个子图里任何两个点都是可达的,所以任何男孩可以随意算则他喜欢的
女孩儿不会导致其他男孩找不到自己喜欢的女孩
(4)强连通分量的计算用到了tarjan算法
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#define MAXN 2005
#define maxv(a, b) ((a) >= (b) ? (a) : (b))
#define minv(a, b) ((a) <= (b) ? (a) : (b))
using namespace std;
struct s
{
vector<int> vec;
}graph[MAXN * 2 + 1];
int sonN;
vector<int> res[MAXN + 1];
stack<int> stackk;
bool processed[MAXN * 2 + 1], inStack[MAXN * 2 + 1], tarjanv[MAXN * 2 + 1];
int id[MAXN * 2 + 1], low[MAXN * 2 + 1], index;
int tempList1[MAXN + 1], len1;
bool tempList2[MAXN + 1];

bool compare(const int &v1, const int &v2)
{
return v1 <= v2;
}
//寻找curid所在的强连通分量
void tarjan(int curid)
{
tarjanv[curid] = true;
id[curid] = low[curid] = ++index;
stackk.push(curid);
inStack[curid] = true;
vector<int>::iterator iter = graph[curid].vec.begin();
for(; iter != graph[curid].vec.end(); iter++)
{
int toid = *iter;
if(processed[toid]) continue;
if(!tarjanv[toid])
{
tarjan(toid);
low[curid] = minv(low[curid], low[toid]);
}
else if(inStack[toid])
low[curid] = minv(low[curid], id[toid]);
}
//find a strong connected componet
if(id[curid] == low[curid])
{
int toid;
len1 = 0;
memset(tempList2, 0, sizeof(tempList2));
while(true)
{
toid = stackk.top();
stackk.pop();
inStack[toid] = false;
if(toid <= sonN)
tempList1[len1++] = toid;
else tempList2[toid - sonN] = true;
processed[toid] = true;
if(toid == curid) break;
}
for(int i = 0; i < len1; i++)
{
int fromid = tempList1[i];
vector<int>::iterator iter = graph[fromid].vec.begin();
for(; iter != graph[fromid].vec.end(); iter++)
{
int toid = *iter;
if(tempList2[toid - sonN])    res[fromid].push_back(toid - sonN);
}
}
}
}
int main()
{
int i, j;
scanf("%d", &sonN);
for(i = 1; i <= sonN; i++)
{
int gnum;
int girl;
scanf("%d", &gnum);
for(j = 1; j <= gnum; j++)
{
scanf("%d", &girl);
graph[i].vec.push_back(girl + sonN);
}
}
for(i = 1; i <= sonN; i++)
{
scanf("%d", &j);
graph[j + sonN].vec.push_back(i);
}
for(i = 1; i <= sonN; i++)
{
if(!processed[i])
{
while(!stackk.empty()) stackk.pop();
memset(inStack, 0, sizeof(inStack));
memset(tarjanv, 0, sizeof(tarjanv));
index = 0;
tarjan(i);
}
}
for(i = 1; i <= sonN; i++)
{
sort(res[i].begin(), res[i].end(), compare);
vector<int>::iterator iter = res[i].begin();
printf("%d", res[i].size());
for(; iter != res[i].end(); iter++)
printf(" %d", *iter);
printf("/n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: