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

poj 1904 King's Quest 强连通分量

2014-11-20 13:01 337 查看
题意:

有n男n女,每个男的可能喜欢多个女的,男的只能跟自己喜欢的人结婚,现在对每个男的要求一个女子集合,使当他跟其中任何女的结婚后其他的n-1个男的都还有喜欢的女孩可以结婚。输入还给出一组可行的结婚方案。

思路:

经典构图题,把输入给的结婚方案中的n对男女看做n个顶点,如果i对中的男喜欢j对中的女则有一条i到j的有向边,然后求强联通分量,跟男的i在一个联通分量内的女的只要i喜欢都可以娶。

代码:

//poj 1904
//sepNINE
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
const int maxN=2048;
const int maxM=200048;
vector<int> son[maxN],ans[maxN];
int h[maxN],head[maxN],belong[maxN],dfn[maxN],low[maxN],ins[maxN];
int n,e,index,cnt;
stack<int> s;
struct Edge{
	int v,next;
}edge[maxM];
void addEdge(int a,int b)
{
	edge[e].v=b;edge[e].next=head[a];head[a]=e++;
}

void tarjan(int u)
{
	dfn[u]=low[u]=++index;
	s.push(u);
	ins[u]=1;
	for(int i=head[u];i!=-1;i=edge[i].next){
		int v=edge[i].v;
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);		
		}else if(ins[v]==1)
			low[u]=min(low[u],dfn[v]);
	}
	int k;
	if(low[u]==dfn[u]){
		++cnt;
		do{
			k=s.top();
			s.pop();
			ins[k]=0;
			belong[k]=cnt;
		}while(dfn[k]!=low[k]);
	}
} 
int main()
{
	int i,j;
	e=0;
	memset(head,-1,sizeof(head));
	scanf("%d",&n);
	for(i=1;i<=n;++i){
		int x;
		scanf("%d",&x);
		while(x--){
		
			int a;
			scanf("%d",&a);
			son[i].push_back(a);
		}
		sort(son[i].begin(),son[i].end());
	}

	for(i=1;i<=n;++i){
		int a;
		scanf("%d",&a);
		h[a]=i;
	}
	for(i=1;i<=n;++i){
		int num=son[i].size();
		for(j=0;j<num;++j){
			int y=h[son[i][j]];
			if(y!=i)
				addEdge(i,y);	
		}
	}
	memset(dfn,0,sizeof(dfn));
	memset(ins,0,sizeof(ins));
	while(!s.empty()) s.pop();
	index=cnt=0;

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