UVA1327 && POJ1904 King's Quest(tarjan+巧妙建图+强连通分量+缩点)
2019-07-18 23:29
1851 查看
UVA1327 King's Quest
POJ1904 King's Quest
题意:
有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚。现有一个匹配表,将每个王子都与一个自己喜欢的妹子配对。请你根据这个表得出每个王子可以和几个自己喜欢的妹子结婚,按序号升序输出妹子的编号,这个表应满足所有的王子最终都有妹子和他结婚(一个妹子只能嫁给一个王子)。
看到题目时,一脸懵逼,只觉得题面很有(ci)趣(ji)
但没办法啊,为了王国的一夫一妻制我们只好努力啊awa
解析:
让我们首先来考虑建图
如果王子u喜欢妹子v那我们可以从u向v连一条有向边
如果妹子v可以与王子u配对(即在配对表上),那我们可以从v向u连一条有向边
对于样例
4 2 1 2 2 1 2 2 2 3 2 3 4 1 2 3 4
我们建出了这样一张图:
红的是王子,蓝的是妹子,绿的表示从王子到公主,黄的表示从妹子到王子
仔细观察我们发现了这张图的一些特别之处:
每个紫色框出的部分都是个强连通分量!
这意味着什么?
这说明这个分量内的每个王子和这个分量内的每个妹子都可以随意匹配
答案只需要枚举王子和他所在分量内的妹子即可
而这个强连通分量又该咋求呢?
当然就是tarjan啦
tips1.UVA的题目是有多组数据的,POJ的每个点只有一组数据,下面的的代码以多组数据为例,但POJ上也能过
tips2.代码中王子编号1..n,妹子编号n+1..2n
代码:
/* read() write()可以换成你自己的快读快输,因为这题数据很多 */ template<class t> void Write(t x,char c){ putchar(c);write(x); } const int N=2e3+5,M=2e5+N; int en,h[N<<1],n,m,dfn[N<<1],low[N<<1],st[N<<1],num,cnt,bel[N<<1],top,ans ; struct edge{int n,v;}e[M]; //前向星存边 inline void add(const int &x,const int &y){e[++en]=(edge){h[x],y};h[x]=en;} void tarjan(int x){ //tarjan求强连通分量 st[++top]=x; //手打堆 dfn[x]=low[x]=++num; for(int i=h[x];i;i=e[i].n){ int y=e[i].v; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); } else if(!bel[y]) low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]){ cnt++; int TOP; do{ TOP=st[top--]; bel[TOP]=cnt; //表示每个王子的所属强连通分量 }while(TOP!=x); } } signed main(){ while(~scanf("%d",&n)){ en=num=cnt=top=0; memset(h,0,sizeof h); memset(dfn,0,sizeof dfn); memset(low,0,sizeof low); memset(bel,0,sizeof bel); for(int i=1,k;i<=n;i++){ read(k); for(int j=1,x;j<=k;j++){ read(x); add(i,x+n); //从王子向妹子连边 } } for(int i=1,x;i<=n;i++){ read(x); add(x+n,i); //从妹子向王子连边 } for(int i=1;i<=n<<1;i++) if(!dfn[i]) tarjan(i); //跑tarjan for(int u=1;u<=n;u++){ //枚举王子 int nm=0; for(int i=h[u];i;i=e[i].n){ //枚举王子喜欢的妹子 int v=e[i].v; if(bel[u]==bel[v]) ans[++nm]=v-n; //判断王子和妹子是否在同一强连通分量中 } sort(ans+1,ans+1+nm); //要求按妹子编号升序输出 write(nm); //每个王子的可匹配妹子数 for(int i=1;i<=nm;i++) Write(ans[i],' '); puts(""); } } }
相关文章推荐
- POJ1904 King's Quest(Tarjan 求缩点)
- ZOJ2470 POJ1904 King's Quest,强连通分量
- poj1904 King's Quest 强连通分量
- POJ1904 King's Quest(完备匹配可行边:强连通分量)
- poj 1904 King's Quest(Tarjan+匹配)
- poj 1904 King's Quest tarjan求二分图的所有可选最大匹配边
- pku 1904 King's Quest tarjan求强连通分量
- poj1904 King's Quest
- UVa 402 M*A*S*H (STL&list)
- UVa 103 Stacking Boxes (DP&DAG)
- uva-10010 - Where's Waldorf?
- UVa 108 Maximum Sum (贪心&最大子矩阵和)
- uva753 (建图 & 最大流)
- POJ 3928 & hdu 2492 & Uva1428 PingPong 【树状数组】
- HDU - 1285 确定比赛名次 &&UVA - 10305 Ordering Tasks (拓扑排序)
- uva 1382 Distant Galaxy (枚举&&扫描&&贪心dp)
- 例题6-7 UVa122 Trees on the level(树&&队列BFS&&sscanf字符串转整数)
- Uva 437 巴比伦塔 && UVA10003
- UVA 10026 Shoemaker's Problem
- uva 11324 The Largest Clique(图论-tarjan,动态规划)