博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj 1904(强连通分量+输入输出外挂)
阅读量:4921 次
发布时间:2019-06-11

本文共 2702 字,大约阅读时间需要 9 分钟。

题目链接:

题意:有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚,大臣给出一个匹配表,每个王子都和一个妹子结婚,但是国王不满意,他要求大臣给他另一个表,每个王子可以和几个妹子结婚,按序号升序输出妹子的编号,这个表应满足所有的王子最终都有妹子和他结婚。

分析:很好的图论题,把强连通分量和完美匹配结合起来了,记得多校的时候看到类似的题目(),但是不会做,还以为是二分匹配=_=

首先建图,如果王子u喜欢妹子v,则建一条边u指向v(u,v),对于大臣给出的初始完美匹配,如果王子u和妹子v结婚,则建一条边v指向u(v,u),然后求强连通分量,

对于每个王子和妹子,如果他们都在同一个强连通分量内,则他们可以结婚。

为什么呢?因为每个王子只能和喜欢的妹子结婚,初始完美匹配中的丈夫和妻子之间有两条方向不同的边可以互达,则同一个强连通分量中的王子数和妹子数一定是相等的,若王子x可以和另外的一个妹子a结婚,妹子a的原配王子y肯定能找到另外一个妹子b结婚,因为如果找不到的话,则x和a必不在同一个强连通分量中。

所以一个王子可以和所有与他同一强连通分量的妹子结婚,而这不会导致同一强连通分量中的其他王子找不到妹子结婚。

好像很绕的样子@_@。。。。。大家在纸上画画图吧

建图的时候王子从1~n编号,妹子从n+1~2*n编号

这一题的数据量挺大的,光是输入输出就会消耗很多时间了,可以用输入输出外挂来加速读入和输出。

不加输入外挂9000+ms

加输入外挂8000+ms

加输入输出外挂500+ms

AC代码:

1 #include
2 #include
3 #include
4 using namespace std; 5 6 const int N=4000+5; 7 const int M=200000+4000; 8 struct EDGE{ 9 int v,next; 10 }edge[M]; 11 int first[N],low[N],dfn[N],sta[M],belong[N],ans[N]; 12 bool instack[N]; 13 int g,cnt,top,scc; 14 15 void AddEdge(int u,int v) 16 { 17 edge[g].v=v; 18 edge[g].next=first[u]; 19 first[u]=g++; 20 } 21 int min(int a,int b) 22 { 23 return a
='0'&&ch<='9') 61 res=ch-'0'; 62 while((ch=getchar())>='0'&&ch<='9') 63 res=res*10+ch-'0'; 64 return flag?-res:res; 65 } 66 void Out(int a) //输出外挂 67 { 68 if(a>9) 69 Out(a/10); 70 putchar(a%10+'0'); 71 } 72 int main() 73 { 74 int n,i,u,v,k; 75 while(scanf("%d",&n)!=EOF) 76 { 77 g=cnt=top=scc=0; 78 memset(first,-1,sizeof(first)); 79 memset(dfn,0,sizeof(dfn)); 80 memset(instack,false,sizeof(instack)); 81 for(i=1;i<=n;i++) 82 { 83 // scanf("%d",&k); 84 k=Scan(); 85 while(k--) 86 { 87 // scanf("%d",&v); 88 v=Scan(); 89 AddEdge(i,v+n); //王子i喜欢妹子v 90 } 91 } 92 for(i=1;i<=n;i++) 93 { 94 // scanf("%d",&v); 95 v=Scan(); 96 AddEdge(v+n,i); //王子i可以和妹子v结婚 97 } 98 99 for(i=1;i<=2*n;i++) //求强连通分量100 if(!dfn[i])101 Tarjan(i);102 103 for(u=1;u<=n;u++)104 {105 int count=0;106 for(i=first[u];i!=-1;i=edge[i].next)107 {108 v=edge[i].v;109 if(belong[u]==belong[v]) //同一个强连通分量110 ans[count++]=v-n;111 }112 sort(ans,ans+count);113 // printf("%d",count);114 Out(count);115 for(i=0;i
View Code

 

转载于:https://www.cnblogs.com/frog112111/p/3384261.html

你可能感兴趣的文章
UVA 208 Firetruck (DFS+剪枝)
查看>>
windows设置电脑的固定IP
查看>>
Python
查看>>
犀牛Phinoceros 如何切换中文语言
查看>>
Win7如何解决精简版的迅雷7无法运行
查看>>
C#.NET常见问题(FAQ)-如何判断某个字符是否为汉字
查看>>
数据的类型以及内置方法
查看>>
继承之super关键字的使用
查看>>
XML - 报表数据的新大陆
查看>>
echart在X轴下方添加字
查看>>
Map集合的两种取出方式
查看>>
GridView,Repeater增加自动序号列
查看>>
SMO算法精解
查看>>
第k小元素学习记录
查看>>
avi文件格式详解【转】
查看>>
django
查看>>
Java学习从入门到精通
查看>>
查找目录下的所有文件中是否含有某个字符串 linux
查看>>
2018年各大互联网前端面试题四(美团)
查看>>
一起学Python:字符串介绍
查看>>