POJ - 3352 无向图的割和桥以及双连通分量

原创 2011年10月17日 13:48:31

    双连通分量是指图中每两个点都有两条完全不同的路径可到达..也就是去掉这个图的任意一个边一个点...两两之间依然可达..  

    图论中的桥...在有向图中是两个连通分量之间唯一的边(如果有多条那么都不是桥)...在无向图中是两个双连通分量之间的唯一边...

    而割指的是割点..割点肯定是和桥的端点...但桥的端点不一是割点..如:


   (1,4),(2,4),(3,4),(4,5),(4,6),(4,7)都是桥..所有点都是桥的端点...但是只有4是割点...1,2,3,5,6,7都不是割点..

   去掉一个连通图中的一个桥或者割点..这个连通图就将成为不连通的多个连通图..

   求无向图中的桥的方法是有Tarjan发明的..Byvoid大大的讲解很给力: http://www.byvoid.com/blog/biconnect/

   无向图的Tarjan和有向图求强连通分量的Tarjan很像...注意几个不同...

    1、求双联通分量时..同样要用到栈..但栈中不是放点..而是放边....

      2、DFS时不能从 a 递归到了 b..b又马上从a来更新...所以要多加一个notpre..代表递归b时是从哪个点进去的...防止这种情况..

      3、Low相等的点在无向图中就是在一个双连通图中...这个比有向图的方便..有向图还需要用栈来维护..通过判断退栈来判断强连通分量..

   如果要求桥和割点的话..做完Tarjan..扫描所有的边,有 DFN ( 终点 ) < LOW ( 起点 ) 的边就是桥...这条边的"终点"就是割点..

   回到POJ3352...题目给出了连通的无向图..并且两点直接最多只有一条边...求的是加几条边能使得该无向图整个变成一个双连通图..

   那么先对图做无向图的Tarjan...得到每个点所在的双连通记录在Low里....可以想象一下..如果把所有的双连通分量分别缩成一个点...那么整个图就是一棵树了..如果给一棵树..要史其成为一个双连通图...那么需要加( 叶子结点数+1)/2调边...

   这道题就是在做完Tarjan找作为叶子节点的双连通分量的个数k..然后答案就是(k+1)/2...

Program:

// POJ3352 加边做双连通图
#include<iostream>
#include<stack>
#include<math.h>
#define MAXN 5001
using namespace std;
struct pp
{  
    int x,y,next;   
}line[MAXN*5];
int n,m,link[MAXN],i,p,low[MAXN],dfn[MAXN],tp[MAXN],numtp,sum[MAXN];
bool instack[MAXN],used[MAXN];
stack<int> mystack;
void trajin(int h)
{
   int k;
   instack[h]=true;
   mystack.push(h);
   low[h]=dfn[h]=++p;
   k=link[h];
   while (k)
   {
      if (!dfn[line[k].y])
      {
            trajin(line[k].y);
            low[h]=min(low[h],low[line[k].y]);     
      }else
      if (instack[line[k].y])
      {
            low[h]=min(low[h],dfn[line[k].y]);           
      }
      k=line[k].next;   
   }
   k=h;
   if (low[k]==dfn[k])
   {
        numtp++;              
        do 
        {
             k=mystack.top();
             tp[k]=numtp;
             mystack.pop();
             instack[k]=false;         
        }while ( low[k]!=dfn[k]);              
   }
   return; 
} 
void getanswer()
{
    int i;
    memset(instack,false,sizeof(instack));
    while (!mystack.empty()) mystack.pop();
    memset(tp,0,sizeof(tp));
    memset(dfn,0,sizeof(dfn));
    p=0; numtp=0;
    for (i=1;i<=n;i++) 
     if (!dfn[i]) 
       trajin(i); 
    for (i=1;i<=n;i++)
     if (!tp[i])
     {
         printf("\n");
         return;           
     }   
    memset(link,0,sizeof(link));
    memset(sum,0,sizeof(sum)); 
    for (i=1;i<=m;i++)
    if (tp[line[i].x]!=tp[line[i].y])
    {
        p++;
        sum[tp[line[i].x]]++;
    }   
    for (i=1;i<=n;i++)
     if (!sum[tp[i]]) 
       printf("%d ",i);  
    printf("\n");
    return;
}
int main()
{ 
    while (~scanf("%d%",&n))
    {
          if (!n) break;
          scanf("%d",&m);
          memset(link,0,sizeof(link));
          memset(line,0,sizeof(line));
          for (i=1;i<=m;i++)
          {
              scanf("%d%d",&line[i].x,&line[i].y);
              line[i].next=link[line[i].x];
              link[line[i].x]=i;
          }
          getanswer();
    }
    return 0;   
}






版权声明:本文为博主原创文章,未经博主允许不得转载。

无向图的割顶和桥,无向图的双连通分量入门详解及模板

割顶和桥:对于无向图G,如果删除某个节点u后,连通分量数目增加,则称u为图的割顶;如果删除某条边后,连通分量数目增加,则称该边为图的桥。对于连通图删除割顶或桥后都会使得图不再连通以下我,我们利用dfs...
  • STILLxjy
  • STILLxjy
  • 2017年04月14日 22:56
  • 1527

无向连通图的割点、桥

无向连通图的割点、桥 泳裤王子原创,转载请注明出处 http://blog.csdn.net/tclh123/article/details/6705392 预备知识:        割点集合 ...
  • tclh123
  • tclh123
  • 2011年08月21日 00:40
  • 7239

poj 3352(无向图的双连通分量)

刚开始的时候习惯性的套用了以前的代码------有向图的 tarjan 算法, WA。。。。。意识到无向图的双连通和有向图的强连通是不能互换的,想搜一些讲解来看看,找不到好的资料,只好自己把tarja...
  • Vgo__
  • Vgo__
  • 2011年06月03日 15:49
  • 870

Tarjan三大算法之双连通分量(割点,桥)

Robert Endre Tarjan是一个美国计算机学家,他传奇的一生中发明了无数算法,统称为Tarjan算法。其中最著名的有三个,分别用来求解 1) 无向图的双连通分量 2) 有向图的强连通分...
  • fuyukai
  • fuyukai
  • 2016年04月23日 11:25
  • 5119

poj 3352 求双连通分量 (无向图)

转:http://blog.csdn.net/lin375691011/article/details/18774187题目大意: 给定图G,求最少加多少边可以成为双连通图。解题思路: 1、求图G...
  • Littlewhite520
  • Littlewhite520
  • 2017年05月05日 15:01
  • 203

无向图的割点,桥,双连通分量,有向图的强连通分量总结

一、无向图的割点,桥,双连通分量
  • Guard_Mine
  • Guard_Mine
  • 2014年08月17日 13:30
  • 1617

无向图求双连通分量以及桥

void pbc_dfs(int u, int parent) {//求双连通分量中的边 dfn[u] = low[u] = dfn_now++; foreach e in adjac...
  • gripleaf
  • gripleaf
  • 2012年12月26日 11:04
  • 264

无向图的双连通分量

无向图的双连通分量 点-双连通图:对于一个无向连通图,如果任意两个点至少存在两条”点不重复”的路径,则说这个图是点-双连通的.这个要求等价于任意两条边都在同一个简单环内,即内部无割顶. 注意:孤立...
  • u013480600
  • u013480600
  • 2014年06月16日 21:17
  • 1054

无向图的桥 双连通分量

/* *无向图的桥及边的双连通分量,Tarjan算法O(E) */ #include #include using namespace std; #define MAXN 10000 #def...
  • cqsh3vj2
  • cqsh3vj2
  • 2014年10月14日 22:47
  • 258

poj 3177 & 3352 【无向图双连通分量Tarjan】

题目:poj 3177 & 3352 题意:大概意思就是给你一个无向图,让你添加最少的边,让所有点都双连通。 分析:双连通的定义就是任意两个点至少有两条路可达。 其实做法跟添加最...
  • y990041769
  • y990041769
  • 2014年11月04日 21:38
  • 1210
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ - 3352 无向图的割和桥以及双连通分量
举报原因:
原因补充:

(最多只允许输入30个字)