您的位置:首页 > 其它

poj/pku 1904(强连通分量解决匹配问题)

2011-09-27 16:49 281 查看
题目链接:http://poj.org/problem?id=1904

题意描述:有n个王子和n个美女,每个王子有自己喜欢的美女,保证每个王子都能娶到一个自己喜欢的美女,现在巫师给出了一个王子和美女匹配的方案,但是国王想知道每个王子能够娶到的美女的名单(保证每个王子都能娶到美女)

分析:匹配就是找增广路,假设一个王子i和美女j开始匹配,那么假设王子i要和其他美女匹配,那么美女j必定和其它王子匹配,这里我们连接美女到初始的王子,那么形成的强连通分量里的王子和他喜欢的美女都是可以匹配的

代码:

//注意在同一个强连通分量中的美女并不是都能和在该连通分量王子匹配
//因为有的美女不是王子所喜欢的,所以在同一个强连通分量中找和王子
//匹配的美女时只能找王子所喜欢的
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=4010; //表示点的个数
vector<int>g
;
int a[N/2];
int low
,dfn
,st
,blg
,index,top,cnt;bool vis
;
void tarjan(int u)
{
int v;
low[u]=dfn[u]=index++;
st[++top]=u;
vis[u]=true;
for(int i=0;i<g[u].size();i++)
{
v=g[u][i];
if(dfn[v]==-1)
{
tarjan(v);
if(low[u]>low[v])
low[u]=low[v];
}
else if(low[u]>dfn[v]&&vis[v])low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
cnt++;
int v1;
do
{
v1=st[top];
vis[v1]=false;
blg[v1]=cnt;
top--;
}while(u!=v1);
}
}
int main ()
{
int n,i,j,x,num;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=2*n;i++)//清空向量
g[i].clear();
for(i=1;i<=n;i++)
{
scanf("%d",&num);
for(j=0;j<num;j++)
{
scanf("%d",&x);
g[i].push_back(x+n);
}
}
for(i=1;i<=n;i++)
{
scanf("%d",&x);
g[x+n].push_back(i);
}
memset(low,0,sizeof(low));
memset(dfn,-1,sizeof(dfn));
memset(blg,0,sizeof(blg));
memset(vis,0,sizeof(vis));
index=1;top=0;cnt=0;
for(i=1;i<=n;i++)
if(dfn[i]==-1)
tarjan(i);
for(i=1;i<=n;i++)
{
int t=0;
for(j=0;j<g[i].size();j++)
if(blg[i]==blg[g[i][j]])
a[t++]=g[i][j]-n;
sort(a,a+t);
printf("%d",t);
for(j=0;j<t;j++)
printf(" %d",a[j]);
printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: