标签:
| Time Limit: 15000MS | Memory Limit: 65536K | |
| Total Submissions: 8460 | Accepted: 3087 | |
| Case Time Limit: 2000MS | ||
Description
Input
Output
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
题意:输入n,表示n个王子,接下来n行,每行首先输入nn,表示王子i喜欢的女子有nn个,然后输入这nn个女子的编号。最后一行输入媒婆已经安排好的配对(都是各自王子喜欢的姑娘)。国王要求在每个儿子都能娶到自己喜欢的姑娘的前提下,每个儿子能够娶的姑娘编号。
思路:由于要输出每个王子能配对的姑娘,所以用二分匹配的思路似乎做不了这题,所以建图的时候让王子先给喜欢的姑娘连边,再在媒婆给出的配对里面让姑娘分别对王子连边,然后缩点,缩完点之后看王子和哪些姑娘在同一个强连通分量里边,如果在一个强连通分量里面直接输出就好。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;
const int N=4010;
struct data
{
int to,next;
} tu[N*100];
int head[N];
int ip;
int dfn[N], low[N];///dfn[]表示深搜的步数,low[u]表示u或u的子树能够追溯到的最早的栈中节点的次序号
int sccno[N];///缩点数组,表示某个点对应的缩点值
int step;
int scc_cnt;///强连通分量个数
void init()
{
ip=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
tu[ip].to=v,tu[ip].next=head[u],head[u]=ip++;
}
vector<int> scc[N];///得出来的缩点,scc[i]里面存i这个缩点具体缩了哪些点
stack<int> S;
void dfs(int u)
{
dfn[u] = low[u] = ++step;
S.push(u);
for (int i = head[u]; i !=-1; i=tu[i].next)
{
int v = tu[i].to;
if (!dfn[v])
{
dfs(v);
low[u] = min(low[u], low[v]);
}
else if (!sccno[v])
low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u])
{
scc_cnt += 1;
scc[scc_cnt].clear();
while(1)
{
int x = S.top();
S.pop();
if (sccno[x] != scc_cnt) scc[scc_cnt].push_back(x);
sccno[x] = scc_cnt;
if (x == u) break;
}
}
}
void tarjan(int n)
{
memset(sccno, 0, sizeof(sccno));
memset(dfn, 0, sizeof(dfn));
step = scc_cnt = 0;
for (int i = 1; i <=n; i++)
if (!dfn[i]) dfs(i);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
init();
for(int i=1; i<=n; i++)
{
int nn;
scanf("%d",&nn);
while(nn--)
{
int t;
scanf("%d",&t);
add(i,t+n);
}
}
for(int i=1; i<=n; i++)
{
int t;
scanf("%d",&t);
add(t+n,i);
}
tarjan(n*2);
for(int i=1; i<=n; i++)
{
int s[N*10],ans=0;
for(int j=head[i]; j!=-1; j=tu[j].next)
{
int to=tu[j].to;
if(sccno[i]==sccno[to])
s[ans++]=to-n;
}
sort(s,s+ans);
printf("%d",ans);
for(int i=0; i<ans; i++)
printf(" %d",s[i]);
puts("");
}
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/martinue/article/details/51365957