zoukankan      html  css  js  c++  java
  • [hdu1269]城堡迷宫<tarjan强连通分量>

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1269

    tarjan算法是oi里很常用的一个算法,在理解方面需要多下一些功夫,如果不行直接记模板也行,因为tarjan主要是细节不好理解。。。

    我目前就是记得模板

    然后这道题是个tarjan的裸题,就是把tarjan的模板打出来就可以A了

    虽然我还是WA了很多次,最后总结原因发现是因为多组输入的原因,多组输入的时候n和m可能会单独存在0的情况(不同时为0),而我的初始程序就是只要有零就跳出,然后成功WA了多次(这是何等的窝草啊)

    所以这题其实就是找下强联通个数,如果是一个就可以输出yes,否则输出no

    当然你也可以主动去优化,优化方式就是当出现第一个强联通时不包括所有点就可以输出no然后exit(0)了

    虽然优不优化这题都可以顺利通过

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<stack>
     7 #include<queue>
     8 #include<cstdlib> 
     9 #define maxn 100005
    10 using namespace std;
    11 
    12 struct edge{
    13     int u,v,nxt;
    14 }e[maxn];
    15 int n,m,ans,head[maxn],dfn[maxn],low[maxn],belong[maxn];
    16 
    17 int read(){
    18     int xx=0,ff=1;char ch=getchar();
    19     while(ch<'0'||ch>'9'){if(ch=='-')ff=-1;ch=getchar();}
    20     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
    21     return xx*ff;
    22 }
    23 
    24 int tot;
    25 void adde(int u,int v){
    26     e[tot]=(edge){u,v,head[u]};
    27     head[u]=tot++;
    28 }
    29 
    30 stack<int>s;
    31 int num;
    32 void tarjan(int x){
    33     num++;
    34     dfn[x]=num;low[x]=num;
    35     s.push(x);
    36     for(int i=head[x];i!=-1;i=e[i].nxt){
    37         int v=e[i].v;
    38         if(dfn[v]==0){
    39             tarjan(v);
    40             low[x]=min(low[x],low[v]);
    41         }else{
    42             if(!belong[v]){low[x]=min(low[x],dfn[v]);}
    43         }            
    44     }
    45     if(dfn[x]==low[x]){
    46         ans++;
    47         int u=s.top();
    48         while(u!=x){
    49             belong[u]=ans;
    50             s.pop();
    51             u=s.top();
    52         }belong[u]=ans;s.pop();
    53     }
    54 }
    55 
    56 int main(){
    57     while(1){
    58         n=read();m=read();
    59         if(n==0&&m==0)return 0;
    60         tot=0;num=0;ans=0;
    61         while(!s.empty())s.pop();
    62         memset(dfn,0,sizeof(dfn));
    63         memset(belong,0,sizeof(belong));
    64         memset(low,0,sizeof(low));
    65         memset(head,-1,sizeof(head));    
    66         for(int i=1;i<=m;i++){
    67             int u,v;
    68             u=read();v=read();
    69             adde(u,v);
    70         }    
    71         for(int i=1;i<=n;i++){
    72             if(!dfn[i]){tarjan(i);}
    73         }
    74         if(ans==1)printf("Yes
    ");
    75         else printf("No
    ");    
    76     }
    77 }
    View Code

    【总结】

    tarjan的理解比较难的地方就是他的low数组和low数组的值的变化,建议多结合图例去理解

  • 相关阅读:
    Android Studio 字体和字号调整
    【IDEA】项目中引入Spring MVC
    【Double】double精度问题和int、long除不尽取舍问题
    【进制转换】原码反码和补码的理解以及进制转换
    【工具】SwitchHost的使用
    【工具】谷歌浏览器使用技巧
    【Git和GitHub】学习笔记
    【IE兼容性】代码中多语言样式+IE不兼容解决
    【Trello】使用指南
    【实操】进制转换:除基倒取余法
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7767677.html
Copyright © 2011-2022 走看看