poj 1904 King's Quest 强连通分量

来源:互联网 发布:网络语吃饼什么意思 编辑:程序博客网 时间:2024/05/19 03:24

题意:

有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;} 


0 0
原创粉丝点击