tarjan通俗易懂题

た 入场券 2021-10-18 12:42 567阅读 0赞

洛谷2661

https://www.luogu.org/problemnew/show/P2661

分析:求缩点后成环中,环大小最小的size

ContractedBlock.gif ExpandedBlockStart.gif

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int M=2e5+5;
  4. vector<int>e[M];
  5. int vis[M],dfn[M],low[M],cnt,ans=M;
  6. stack<int>S;
  7. void tarjan(int u){
  8. dfn[u]=low[u]=++cnt;
  9. vis[u]=1;
  10. S.push(u);
  11. for(int i=0;i<e[u].size();i++){
  12. int v=e[u][i];
  13. if(!dfn[v]){
  14. tarjan(v);
  15. low[u]=min(low[u],low[v]);
  16. }
  17. else if(vis[v])
  18. low[u]=min(low[u],dfn[v]);
  19. }
  20. if(low[u]==dfn[u]){
  21. int countt=0;
  22. while(true){
  23. int t=S.top();
  24. S.pop();
  25. vis[t]=0;
  26. countt++;
  27. if(t==u)
  28. break;
  29. }
  30. if(countt>1)
  31. ans=min(ans,countt);
  32. }
  33. }
  34. int main(){
  35. int n;
  36. scanf("%d",&n);
  37. for(int i=1;i<=n;i++){
  38. int x;
  39. scanf("%d",&x);
  40. e[i].push_back(x);
  41. }
  42. for(int i=1;i<=n;i++){
  43. if(!dfn[i])
  44. tarjan(i);
  45. }
  46. cout<<ans;
  47. return 0;
  48. }

https://www.luogu.org/problemnew/show/P1726

分析:还是求环的大小,不过要在存路径时加些操作

ContractedBlock.gif ExpandedBlockStart.gif

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<stack>
  6. #include<vector>
  7. using namespace std;
  8. const int M=5e4+4;
  9. int dfn[M],low[M],vis[M],a[M],b[M],cnt;
  10. vector<int>e[M];
  11. stack<int>S;
  12. int ans;
  13. void tarjan(int u){
  14. dfn[u]=low[u]=++cnt;
  15. vis[u]=1;
  16. S.push(u);
  17. for(int i=0;i<e[u].size();i++){
  18. int v=e[u][i];
  19. if(!dfn[v]){
  20. tarjan(v);
  21. low[u]=min(low[u],low[v]);
  22. }
  23. else if(vis[v])
  24. low[u]=min(low[u],dfn[v]);
  25. }
  26. if(low[u]==dfn[u]){
  27. int countt=0;
  28. while(true){
  29. int t=S.top();
  30. S.pop();
  31. vis[t]=0;
  32. a[countt++]=t;
  33. if(t==u)
  34. break;
  35. }
  36. if(ans<=countt){
  37. sort(a,a+countt);
  38. if(ans==countt){
  39. int flag=0;
  40. for(int i=0;i<countt;i++)
  41. if(a[i]<b[i]){
  42. flag=1;
  43. break;
  44. }
  45. else if(a[i]>b[i])
  46. break;
  47. if(flag==1)
  48. for(int i=0;i<countt;i++)
  49. b[i]=a[i];
  50. }
  51. else{
  52. for(int i=0;i<countt;i++)
  53. b[i]=a[i];
  54. }
  55. ans=countt;
  56. }
  57. }
  58. }
  59. int main(){
  60. int n,m;
  61. scanf("%d%d",&n,&m);
  62. for(int i=1;i<=m;i++){
  63. int u,v,t;
  64. scanf("%d%d%d",&u,&v,&t);
  65. if(t==1)
  66. e[u].push_back(v);
  67. else
  68. e[u].push_back(v),e[v].push_back(u);
  69. }
  70. for(int i=1;i<=n;i++)
  71. if(!dfn[i])
  72. tarjan(i);
  73. printf("%d\n",ans);
  74. for(int i=0;i<ans;i++){
  75. printf("%d ",b[i]);
  76. }
  77. return 0;
  78. }

https://www.luogu.org/problemnew/show/P2341

分析:所求量一定为经缩点后唯一出度为0的强联通分量的大小

ContractedBlock.gif ExpandedBlockStart.gif

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<stack>
  6. #include<vector>
  7. using namespace std;
  8. const int M=1e4+4;
  9. const int N=5e4+5;
  10. vector<int>e[M];
  11. int out[M],in[M],dfn[M],low[M],vis[M],sz[N],cnt,tot,cmp[N];
  12. stack<int>S;
  13. void tarjan(int u){
  14. low[u]=dfn[u]=++cnt;
  15. vis[u]=1;
  16. S.push(u);
  17. for(int i=0;i<e[u].size();i++){
  18. int v=e[u][i];
  19. if(!dfn[v]){
  20. tarjan(v);
  21. low[u]=min(low[u],low[v]);
  22. }
  23. else if(vis[v])
  24. low[u]=min(low[u],dfn[v]);
  25. }
  26. if(dfn[u]==low[u]){
  27. int countt=0;
  28. tot++;
  29. while(true){
  30. int t=S.top();
  31. S.pop();
  32. vis[t]=0;
  33. cmp[t]=tot;
  34. countt++;
  35. if(t==u)
  36. break;
  37. }
  38. sz[tot]=countt;
  39. }
  40. }
  41. int main(){
  42. int n,m;
  43. scanf("%d%d",&n,&m);
  44. int u,v;
  45. for(int i=1;i<=m;i++){
  46. scanf("%d%d",&u,&v);
  47. e[u].push_back(v);
  48. }
  49. for(int i=1;i<=n;i++)
  50. if(!dfn[i])
  51. tarjan(i);
  52. int sum=0;
  53. for(int i=1;i<=n;i++)
  54. for(int j=0;j<e[i].size();j++){
  55. int v=e[i][j];
  56. if(cmp[i]!=cmp[v])
  57. out[cmp[i]]++,in[cmp[v]]++;
  58. }
  59. int countt=0,sign;
  60. for(int i=1;i<=tot;i++)
  61. if(out[i]==0)
  62. countt++,sign=i;
  63. if(countt>1)
  64. return puts("0"),0;
  65. printf("%d\n",sz[sign]);
  66. return 0;
  67. }

转载于:https://www.cnblogs.com/starve/p/11192740.html

发表评论

表情:
评论列表 (有 0 条评论,567人围观)

还没有评论,来说两句吧...

相关阅读

    相关 kmp算法--通俗易懂

    今天花了好几个小时学习这个算法,担心之后忘记,所以在这里做些总结。也方便其它人学习借鉴。 学习理解的过程中也看了很多帖子,但感觉说的都不是特别清楚,也对照了课本,但是大量

    相关 快速排序(通俗易懂

    高快省的排序算法 有没有既不浪费空间又可以快一点的排序算法呢?那就是“快速排序”啦!光听这个名字是不是就觉得很高端呢。 假设我们现在对“6  1  2 7  9  3  4

    相关 快速排序(通俗易懂

    高快省的排序算法 有没有既不浪费空间又可以快一点的排序算法呢?那就是“快速排序”啦!光听这个名字是不是就觉得很高端呢。 假设我们现在对“6  1  2 7  9  3  4

    相关 通俗易懂分布式

    借鉴。原文请[点击这里][Link 1]。 — 分布式不是单单几句java代码就能建立的。如果一定要用java来理解,那java里面的多线程可以理解成一个分布式,他把用户请