码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3594 Cactus /uva 10510 仙人掌图判定

时间:2014-05-03 21:38:39      阅读:250      评论:0      收藏:0      [点我收藏+]

标签:blog   class   code   tar   get   int   

仙人掌图(有向):同时满足:1强连通;2任何边不在俩个环中。

个人理解:其实就是环之间相连,两两只有一个公共点,(其实可以缩块),那个公共点是割点。HDU数据弱,网上很多错误代码和解法也可以过。

个人解法:

我认为:

 :仙人掌图必然是欧拉图!这样只用“入度=出度”就可以简单地判断强连通(欧拉图显然强连通)了!而且这个必要(不充分)条件还秒杀好多数据(强连通++)。

      个人证明:反证法:若有点的入度!=出度,(不妨设入度多),那么,对于每个出度,唯一从对应入度处“回来”,形成以个环,一出一入,一一对应,现在入度多的,只有从之前的出度中“回来”(鸽巢原理),这样该边在俩个环中了,矛盾。即证。

这样只是一个必要条件罢了,还有入度==出度的,但是明显存在很多环的情况,下面用以一种普遍的解法排除即可:用dfs一遍,当发现环时(dfs发现祖先点),标记该环上所有点(祖先点/割点除外),一次,若有一个点标记俩次以上(说明有边同时在俩个环),那么必然是非仙人掌了。

这俩个条件加起来,足以判断仙人掌图。虽然暂时无法证明其充分性,但也举不出反例。

可以在uva10510 提交,数据强一些。

转载请注明出处:http://write.blog.csdn.net/postedit?ref=toolbar

代码:

 

#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
vector<vector<int> >e(100000);
int ind[20010];
int outd[20010];
bool judge1()             //欧拉图判断      
{
    for(int i=0;i<n;i++)
    {
        if(ind[i]!=outd[i])
           return 0;
    }
    return 1;
}
int vis[20010];
int fa[20010];
int mark[20010];
int flag=0;
void set(int u,int vv)   {
     mark[u]++;
     while(u!=vv)
     {
           u=fa[u]; 
           mark[u]++;
           if(mark[u]>1&&u!=vv){flag=1;return ;} 
           if(u==0)break;
     }
     mark[vv]--;
    
}                     
void dfs(int u)
{
     if(flag)return ;
       for(int j=0;j<e[u].size();j++)
           {
              int vv=e[u][j];
                    if(!vis[vv])
                     {  
                                fa[vv]=u;
                                 vis[vv]=1;
                                dfs(vv);
                                
                     }
                    else 
                      set(u,vv);   
           }
     return ;  
}     
bool judge2()           //判定2
{
     vis[0]=1;
     dfs(0);
     if(flag)return 0;
     for(int i=0;i<n;i++)
     {
             if(mark[i]>1)
               return 0;
    }
    return 1;
}                         
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=0;i<=n;i++)
          {
                fa[i]=-1;
              mark[i]=vis[i]=ind[i]=outd[i]=0;
              e[i].clear();
          } 
         flag=0; 
        int ta,tb;
        scanf("%d%d",&ta,&tb);
        while(ta!=0||tb!=0)
        {
            e[ta].push_back(tb);
            outd[ta]++;
            ind[tb]++;
            scanf("%d%d",&ta,&tb);
        }
        
        if(!judge1())
        {
            printf("NO\n");
            continue;
        }
        else
        {
            
            if(!judge2())
              printf("NO\n");
            else  printf("YES\n");
        }
    }
    return 0;
    
}


 

    

 

  

hdu 3594 Cactus /uva 10510 仙人掌图判定,布布扣,bubuko.com

hdu 3594 Cactus /uva 10510 仙人掌图判定

标签:blog   class   code   tar   get   int   

原文地址:http://blog.csdn.net/u011498819/article/details/24921837

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!