标签:scanf lag display none sar cpp dfs gif tchar
https://www.cnblogs.com/violet-acmer/p/9739990.html
参考资料:
[1]:http://www.cnblogs.com/frog112111/p/3384261.html
[2]:https://blog.csdn.net/a709743744/article/details/52133778
[3]:http://www.cppblog.com/Uriel/articles/121169.html
题意:
有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚,大臣给出一个匹配表,每个王子都和一个妹子结婚,但是国王不满意,他要求大臣给他另一个表,每个王子可以和几个妹子结婚,按序号升序输出妹子的编号,这个表应满足所有的王子最终都有妹子和他结婚。
分析:
很好的图论题,把强连通分量和完美匹配结合起来了。
2*N 个顶点的2 分图,并且给了一个完美匹配(Perfect Matching)以及每个顶点可以连接的其他的顶点。
题目要求是否可以确定某 2 个顶点连边后,其他 2*(N - 1) 个顶点的 2 分图是否可以构成完美匹配。
建图:
如果王子u喜欢妹子v,则建一条边u指向v(u,v),对于大臣给出的初始完美匹配,如果王子u和妹子v结婚,则建一条边v指向u(v,u),然后求强连通分量。
对于每个王子和妹子,如果他们都在同一个强连通分量内,则他们可以结婚。
为什么呢?因为每个王子只能和喜欢的妹子结婚,初始完美匹配中的丈夫和妻子之间有两条方向不同的边可以互达,则同一个强连通分量中的王子数和妹子数一定是相等的,若王子 x 可以和另外的一个妹子 a 结婚,妹子 a 的原配王子 y 肯定能找到另外一个妹子 b 结婚,因为如果找不到的话,则 x 和 a 必不在同一个强连通分量中。
所以一个王子可以和所有与他同一强连通分量的妹子结婚,而这不会导致同一强连通分量中的其他王子找不到妹子结婚。
(证明:王子为什么不能选择不同强连通分量的妹子:
反证法:如果强连通分量 1 中的王子选择了强连通分量 2 中的妹子,那么势必强连通分量 2 中的一个王子无法在自己的强连通分量中找到妹子,那么他就会去别的强连通分量找妹子,这样一直循环下去,我们知道最终一定是经过了强连通分量 1,2,x1,x2,xn,……,1,王子们才能都找到自己的妹子,这样这些强连通分量1,2,x1,x2,xn,……,1会构成一个强连通分量,与题设在不同强连通分量中找妹子不符)
此题难点:建图
AC代码:
这一题的数据量挺大的,光是输入输出就会消耗很多时间了,可以用输入输出外挂来加速读入和输出。
Kosaraju算法:
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 #define mem(a,b) memset(a,b,sizeof a) 8 #define pb push_back 9 const int maxV=4e3+50; 10 11 int scc[maxV]; 12 bool vis[maxV]; 13 vector<int >vs; 14 vector<int >edge[maxV],redge[maxV]; 15 16 void addEdge(int u,int v) 17 { 18 edge[u].pb(v); 19 redge[v].pb(u); 20 } 21 void Dfs(int u) 22 { 23 vis[u]=true; 24 for(int i=0;i < edge[u].size();++i) 25 { 26 int to=edge[u][i]; 27 if(!vis[to]) 28 Dfs(to); 29 } 30 vs.pb(u); 31 } 32 void rDfs(int u,int sccId) 33 { 34 scc[u]=sccId; 35 vis[u]=true; 36 for(int i=0;i < redge[u].size();++i) 37 { 38 int to=redge[u][i]; 39 if(!vis[to]) 40 rDfs(to,sccId); 41 } 42 } 43 void Scc(int maxV) 44 { 45 mem(vis,false); 46 vs.clear(); 47 for(int i=1;i <= maxV;++i) 48 if(!vis[i]) 49 Dfs(i); 50 mem(vis,false); 51 int sccId=0; 52 for(int i=vs.size()-1;i >= 0;--i) 53 { 54 int v=vs[i]; 55 if(!vis[v]) 56 { 57 sccId++; 58 rDfs(v,sccId); 59 } 60 } 61 } 62 int main() 63 { 64 int N; 65 scanf("%d",&N); 66 for(int i=1;i <= N;++i) 67 { 68 int k,v; 69 scanf("%d",&k); 70 while(k--) 71 { 72 scanf("%d",&v); 73 addEdge(i,v+N);//王子i喜欢妹子v 74 } 75 } 76 for(int i=1;i <= N;++i) 77 { 78 int v; 79 scanf("%d",&v); 80 addEdge(v+N,i);//王子i可以和妹子v结婚 81 } 82 Scc(N); 83 for(int i=1;i <= N;++i) 84 { 85 int res=0; 86 int ans[maxV]; 87 for(int j=0;j < edge[i].size();++j) 88 { 89 int to=edge[i][j]; 90 if(scc[i] == scc[to])//同一个强连通分量 91 ans[res++]=to; 92 } 93 sort(ans,ans+res); 94 printf("%d",res); 95 for(int j=0;j < res;++j) 96 printf(" %d",ans[j]-N); 97 printf("\n"); 98 } 99 }
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 #define mem(a,b) memset(a,b,sizeof a) 8 #define pb push_back 9 const int maxV=4e3+50; 10 11 int scc[maxV]; 12 bool vis[maxV]; 13 vector<int >vs; 14 vector<int >edge[maxV],redge[maxV]; 15 16 void addEdge(int u,int v) 17 { 18 edge[u].pb(v); 19 redge[v].pb(u); 20 } 21 void Dfs(int u) 22 { 23 vis[u]=true; 24 for(int i=0;i < edge[u].size();++i) 25 { 26 int to=edge[u][i]; 27 if(!vis[to]) 28 Dfs(to); 29 } 30 vs.pb(u); 31 } 32 void rDfs(int u,int sccId) 33 { 34 scc[u]=sccId; 35 vis[u]=true; 36 for(int i=0;i < redge[u].size();++i) 37 { 38 int to=redge[u][i]; 39 if(!vis[to]) 40 rDfs(to,sccId); 41 } 42 } 43 void Scc(int maxV) 44 { 45 mem(vis,false); 46 vs.clear(); 47 for(int i=1;i <= maxV;++i) 48 if(!vis[i]) 49 Dfs(i); 50 mem(vis,false); 51 int sccId=0; 52 for(int i=vs.size()-1;i >= 0;--i) 53 { 54 int v=vs[i]; 55 if(!vis[v]) 56 { 57 sccId++; 58 rDfs(v,sccId); 59 } 60 } 61 } 62 //===============输入输出挂=============== 63 int Scan() //输入外挂 64 { 65 int res=0,ch,flag=0; 66 if((ch=getchar())==‘-‘) 67 flag=1; 68 else if(ch>=‘0‘&&ch<=‘9‘) 69 res=ch-‘0‘; 70 while((ch=getchar())>=‘0‘&&ch<=‘9‘) 71 res=res*10+ch-‘0‘; 72 73 return flag?-res:res; 74 } 75 void Out(int a) //输出外挂 76 { 77 if(a>9) 78 Out(a/10); 79 putchar(a%10+‘0‘); 80 } 81 //======================================== 82 int main() 83 { 84 int N; 85 scanf("%d",&N); 86 for(int i=1;i <= N;++i) 87 { 88 int k,v; 89 //scanf("%d",&k); 90 k=Scan(); 91 while(k--) 92 { 93 //scanf("%d",&v); 94 v=Scan(); 95 addEdge(i,v+N);//王子i喜欢妹子v 96 } 97 } 98 for(int i=1;i <= N;++i) 99 { 100 int v; 101 //scanf("%d",&v); 102 v=Scan(); 103 addEdge(v+N,i);//王子i可以和妹子v结婚 104 } 105 Scc(N); 106 for(int i=1;i <= N;++i) 107 { 108 int res=0; 109 int ans[maxV]; 110 for(int j=0;j < edge[i].size();++j) 111 { 112 int to=edge[i][j]; 113 if(scc[i] == scc[to])//同一个强连通分量 114 ans[res++]=to; 115 } 116 sort(ans,ans+res); 117 //printf("%d",res); 118 Out(res); 119 for(int j=0;j < res;++j) 120 { 121 printf(" "); 122 Out(ans[j]-N); 123 //printf(" %d",ans[j]-N); 124 } 125 printf("\n"); 126 } 127 }
好晚了,身心疲惫,明天在补Tarjan算法...............
标签:scanf lag display none sar cpp dfs gif tchar
原文地址:https://www.cnblogs.com/violet-acmer/p/9741009.html