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

pku 1904 King's Quest tarjan求强连通分量

2012-02-15 09:08 411 查看
http://poj.org/problem?id=1904

很多人都说是二分匹配题目,可是我还没有接触他呢。悲剧啊。不过这道题要求强连通分量做。

king有n个儿子,这边有n个beautiful mm,每个儿子可以喜欢多个mm,但是只能和一个结婚。最后king的wizard给出了一个完美匹配。

可是国王比较定眼,想知道每个儿子所有可以结婚的情况。

儿子编号(1,n) mm编号(n+1, 2*n),儿子喜欢mm就建立一条边 u ->v 如果儿子取了mm 在建立一条边 v->u然后求强连通分量,在一个强连通分量里的是他所有可能结婚的情况

View Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
#define maxn 20012
using namespace std;
int low[maxn],dfn[maxn],belong[maxn];
bool instack[maxn];
vector<int>g[maxn];
stack<int>s;
int n,m;
int bcnt,index;
void init()
{
for (int i = 0; i < maxn; ++i)
{
g[i].clear();
low[i] = dfn[i] = belong[i] = 0;
instack[i] = false ;
}
while (!s.empty()) s.pop();
index = bcnt = 0;
}
void tarjan(int i)
{
int j,k;
low[i] = dfn[i] = ++index;
s.push(i);
instack[i] = true;
for (k = 0; k < g[i].size(); ++k)
{
j = g[i][k];
if (!dfn[j])
{
tarjan(j);
low[i] = min(low[i],low[j]);
}
else if (instack[j])
{
low[i] = min(low[i],dfn[j]);
}
}
if (low[i] == dfn[i])
{
bcnt++;
do
{
j = s.top();
s.pop();
instack[j] = false;
belong[j] = bcnt;
} while (j != i);
}
}
int main()
{
//freopen("d.txt","r",stdin);
int i,j,k;
int x;
while (~scanf("%d",&n))
{

init();

for (i = 1; i <= n; ++i)
{
cin>>m;
for (j = 0; j < m; ++j)
{
cin>>x;
g[i].push_back(x+n);
}
}
for (i = 1; i <= n; ++i)
{
cin>>x;
g[x+n].push_back(i);
}
for (i = 1; i <= 2*n; ++i)
{
if (!dfn[i]) tarjan(i);
}
vector<int>temp;
for (i = 1; i <= n; ++i)
{

for (j = 0; j < g[i].size(); ++j)
{
k = g[i][j];
if (belong[i] == belong[k])
temp.push_back(k);
}
printf("%d",temp.size());
sort(temp.begin(),temp.end());
for (k = 0; k < temp.size(); ++k)
printf(" %d",temp[k]-n);
temp.clear();
printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: