zoukankan      html  css  js  c++  java
  • hdu 3594 Cactus

    这题因为只有10组数据,输出只有YES和NO,所以就出现了各种水过的代码,好题不能就这样埋没掉啊,题解~~

    这题巧妙的利用了Tarjan强连通算法low[]数组,根据仙人掌图的三个性质判断是否是仙人掌图,详细证明这里

    性质1 仙人掌图的DFS树没有横向边。

    性质2 Low(v)<=DFN(u) (v是u的儿子)

    性质3 设某个点v有a(u)个儿子的Low值小于DFS(u),同时u自己有b(u)条逆向边。那么a(u)+b(u)<2。

     1 #include<cstdio>
    2 #include<cstring>
    3 using namespace std;
    4 #define MIN(x,y) (x>y?y:x)
    5 #define N 20005
    6 #define M 50005
    7
    8 struct Edge{
    9 int vtx,next;
    10 Edge(){}
    11 Edge(int v,int n):
    12 vtx(v),next(n){}
    13 }E[M];
    14 int head[N],size;
    15 int dfn[N],low[N],step,scc;
    16 int stk[N],top;
    17 bool ins[N],udfs[N];
    18
    19 void Init(){
    20 memset(head,-1,sizeof(head));
    21 memset(dfn,-1,sizeof(dfn));
    22 memset(ins,false,sizeof(ins));
    23 memset(udfs,false,sizeof(udfs));
    24 size=step=scc=0; top=-1;
    25 }
    26
    27 void Insert(int u,int v){
    28 E[size]=Edge(v,head[u]);
    29 head[u]=size++;
    30 }
    31
    32 bool Tarjan(int u){
    33 stk[++top]=u; ins[u]=true;
    34 dfn[u]=low[u]=step++;
    35 int cnt=0;
    36 for(int i=head[u];i!=-1;i=E[i].next){
    37 int v=E[i].vtx;
    38 if(udfs[v]) return false; //udfs[]数组表示该点是否被遍历过(该点的dfs树已经被全部遍历),如果某个点指向一个被遍历过的点,则出现横向边,返回false,性质1
    39 if(dfn[v]==-1){
    40 if(!Tarjan(v)) return false;
    41 if(low[v]>dfn[u]) return false; //子孩子的low值大于当前点的dfn值,说明不是连通图,返回false,性质2
    42 if(low[v]<dfn[u]) cnt++; //子孩子中low小于该点dfn的个数,即a(u)
    43 if(cnt==2) return false; //如果a(u)+b(u)>=2 ,返回false,性质3
    44 low[u]=MIN(low[u],low[v]);
    45 }else if(ins[v]){
    46 low[u]=MIN(low[u],dfn[v]);
    47 cnt++;//该节点存在逆向边的个数,即b(u)
    48 if(cnt==2) return false; //同上
    49 }
    50 }
    51 udfs[u]=true; //该点dfs结束,标记
    52 return true;
    53 }
    54
    55 int main(){
    56 int t;
    57 scanf("%d",&t);
    58 while(t--){
    59 int n;
    60 scanf("%d",&n);
    61 Init();
    62 while(true){
    63 int u,v;
    64 scanf("%d%d",&u,&v);
    65 if(u==0&&v==0) break;
    66 Insert(u,v);
    67 }
    68 bool flag=Tarjan(0);
    69 if(flag){ //如果还存在没有被遍历到的点,则该图不连通,标程竟然没判断这个
    70 for(int i=0;i<n;i++){
    71 if(dfn[i]==-1){flag=false;break;}
    72 }
    73 }
    74 puts(flag?"YES":"NO");
    75 }
    76 }

      

  • 相关阅读:
    CentOS6.5安装Tab增强版:bash-completion
    005_linux下logrotate 配置和理解
    ITIL与ITSM的联系与区别
    C++----练习--bool类型作为特别的int要区别对待
    C++----练习--while求和
    C++----练习
    mysql----二进制包安装
    linux----ulimit 限制
    python----特性003
    python----特性002
  • 原文地址:https://www.cnblogs.com/ambition/p/Cactus.html
Copyright © 2011-2022 走看看