题意:某个企业想把一个热带天堂岛变成旅游胜地,岛上有N个旅游景点,任意2个旅游景点之间有路径连通(注意不一定是直接连通)。而为了给游客提供更方便的服务,该企业要求道路部门在某些道路增加一些设施。
道路部门每次只会选择一条道路施工,在该条道路施工完毕前,其他道路依然可以通行。然而有道路部门正在施工的道路,在施工完毕前是禁止游客通行的。这就导致了在施工期间游客可能无法到达一些景点。
为了在施工期间所有旅游景点依然能够正常对游客开放,该企业决定搭建一些临时桥梁,使得不管道路部门选在哪条路进行施工,游客都能够到达所有旅游景点。给出当下允许通行的R条道路,问该企业至少再搭建几条临时桥梁,才能使得游客无视道路部门的存在到达所有旅游景点?
解题思路:赤裸裸的求边双连通缩点的题目,明显这是问至少加多少条边,才能把给出的图变成边双连通图,那么这题就是求边双连通图的构造问题了,又是很死很模板的事情了,直接用模板先求边双连通缩点,重构一个边双连通缩点树,那么这棵树的树叶数就是要加入的边数的一个指标了,(树叶数+1)/2就是要加入的边数了,一开始没注意,都是细节上的问题,自我测试时有几组数据没过,后来还是改好了,细节细节细节.....
128msG++代码
#include
#include
#include
#include
#include
#include 
#include
#include
using namespace std;
vectorg[1005];
int bn[1005][1005];
stackst;
bool vis[1005];
int dfn[1005],low[1005],n,m,ans,num,btch,d[1005],belone[1005];

void tarjan(int i,int fa)
{
 dfn[i]=low[i]=++num;
 vis[i]=true;
 st.push(i);
 int flag=1;
 for(int j=0;j {
  int v=g[i][j];
  if(fa==v&&flag)
  {
   flag=0;
   continue;
  }
  if(!vis[v])
  {
   tarjan(v,i);
   low[i]=min(low[v],low[i]);
   if(dfn[i]   {
    int min=0,x;
    btch++;
    do
    {
     x=st.top();
     belone[x]=btch;
     st.pop();
    }
    while(x!=v);

   }
  }
  else
   low[i]=min(low[i],dfn[v]);
 }
}


int main()
{
 int i,x,y,j;
 while(scanf("%d %d",&n,&m)!=EOF)
 {
  num=btch=ans=0;
  for(i=0;i<=n;i++)
  {
   vis[i]=false;
   g[i].clear();
   d[i]=0;
   belone[i]=0;
  }
  for(i=1;i<=m;i++)
  {
   scanf("%d %d",&x,&y);
   g[x].push_back(y);
   g[y].push_back(x);
  }
  tarjan(1,-1);
  memset(bn,0,sizeof(bn));
  for(i=1;i<=n;i++)
  {
   for(j=0;j   {
    int v=g[i][j];
    if(belone[i]!=belone[v]&&(bn[belone[i]][belone[v]]==0&&bn[belone[v]][belone[i]]==0))
    {
     d[belone[i]]++;
     d[belone[v]]++;
     bn[belone[i]][belone[v]]=bn[belone[v]][belone[i]]=1;
    }
   }
  }

  ans=0;
  for(i=0;i<=btch;i++)
  {
   if(d[i]==1)
    ans++;
  }
  printf("%d\n",(ans+1)/2);


 }
 return 0;
}