poj 3177 缩点,双连通分量

算法:

就是给你一个无向图,至少添加几条边,使得从fieldsi 到fields j的路径至少有两条以上。

转化为问题:

添加几条边使得图变成双连通图。。

方法:

1.用tarjian算法缩点。。

2.根据公式计算。。

若要使得任意一棵树,在增加若干条边后,变成一个双连通图,那么

至少增加的边数 =( 这棵树总度数为1的结点数 + 1 )/ 2

来自:http://blog.csdn.net/lyy289065406/article/details/6762370

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<string>
#include<math.h>
#include<map>
#include<set>
#include<stack>
#include<algorithm>
using namespace std;

#define MAXN 100010
struct Edge
{
 int v, next;
 Edge() { }
 Edge( int V, int Next): v(V), next(Next) {}
}edge[MAXN];


int head[MAXN],d[MAXN], low[MAXN], visit[MAXN],degree[MAXN], e, F, R, ptime, cnt;
stack<int>p;

void init( )
{
  e = 0;
  ptime = 0;
  cnt = 0;
  memset(head, -1, sizeof(head)); 
  memset(d, 0, sizeof(d));
  memset(low, 0, sizeof(low));
  memset(visit,0,sizeof(visit));
  memset(degree,0,sizeof(degree));
}

int jugde( int u, int v)
{
  for( int e = head[u]; e != -1; e = edge[e].next)
  {
     if( edge[e].v == v )
        return 1;      
        
  }    
  return 0;  
}

void AddEdge( int u, int v)
{
  if( jugde(u,v) )
    return;
  edge[e] = Edge(v, head[u]);
  head[u] = e++;
  edge[e] = Edge(u, head[v]);
  head[v] = e++;
}

void tarjian(int u, int pf)
{
   d[u] = low[u] = ++ptime; 
   for( int e = head[u]; e != -1; e = edge[e].next)
   {
        int v = edge[e].v;
        if( v == pf ) continue;
        if( !d[v] )
        {
           tarjian(v, u);
           low[u] = min(low[u], low[v]); 
        }  
        else 
        {  
           low[u] = min(low[u], d[v]);        
        }
   }
       
}

int solve( )
{
   for( int i = 1; i <= F; i++)
   {
       for( int e = head[i]; e != -1; e = edge[e].next)
       {
           int v = edge[e].v;
           if( low[i] != low[v] )
           {
              degree[low[i]]++;
              degree[low[v]]++;     
           }
       
       }     
        
   }
   int cnt = 0;
   for( int i = 0; i <= ptime; i++)
   {
       if( degree[i] / 2 == 1 )
               cnt++;  
   }    
   return (cnt + 1) / 2;
}

int main( )
{
  int a, b;
  while( scanf("%d%d", &F, &R) != EOF)
  {
      init( );
      for( int i = 1; i <= R; i++)
      {
          scanf("%d%d",&a,&b);
          AddEdge(a, b);      
      }
      for( int i = 1; i <= F; i++)
      {
          if( !d[i] )
            tarjian( i , i);
      }
      printf("%d\n",solve( ));     
         
  }
  return 0;
}

 

 

posted on 2012-09-24 18:32  more think, more gains  阅读(198)  评论(0编辑  收藏  举报

导航