POJ3352 Road Construction【边双联通分量】【Tarjan】

题目链接:

?id=3352

题目大意:

一个热带天堂岛上有N个旅游景点,任意2个旅游景点之间都有路径(并不一定直接相连)。为了使游客

往返更便捷,该旅游公司要求增加一些道路。在施工的时候,每次只能选择一条道路施工,在施工完

毕之前,除了该道路意外,其他道路依旧能够通行。因为施工道路禁止通行,这就导致了在施工期间

游客可能无法到达一些经典。

该公司为了保证在施工期间所有的旅游景点都能够向游客开放,该公司决定搭建一些临时桥梁,使得

无论在哪条道路施工,游客都能到达所有的旅游景点。那么问题来了:给你N个景点和M条双向边,

问:最少搭建几条临时桥梁,才能够使无论在哪条道路施工,都不会影响游客达到所有的旅游景点。

思路:

题目可以转变为:给你一个无向连通图,问至少添加几条边,,才能变成双连通图。下边我们来考虑这

道题。当图中存在割边(桥)的时候,删掉它,显然构不成双连通图。割边的两端分属于两个边连通分

量。删除它原图就分成了两个边连通分量。所以必须在两个边连通分量之间再添加一条边(也就是题目

边连通分量,怎么添加临时边,才能使得任意两个边连通分量之间都成为双连通。

(1)找出原图的所有边连通分量。

(2)对原图进行缩点,将同属一个边连通分量的点看做一个点。

(3)求缩点后,最少添加几条双向边,使得全部点之间都能够直接到达。

关于第三步,参考下图来说明解决方法:

原图G缩点后如右图所示。若使得所有边连通分量之间都成为双连通。就得使右图中A、B、C、D之间

能够相互连接。可以明显看出右图再添加2条边就可以满足要求。添加(A、B),使得A、B、D相互双连

通。再添加(B、C)或(A、C)使得A、B、C、D全部相互双连通。

那么第三步求出缩点后所有度数为1的点个数。结果ans = (缩点后度数为1的点个数+1) / 2。

参考博文:

AC代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;const int MAXN = 1100;const int MAXM = 5500;struct EdgeNode{int to;int next;}Edges[MAXM];int Head[MAXN];int dfn[MAXN],low[MAXN],Stack[MAXN],degree[MAXN];int m,id,scc,lay,M,N;void AddEdges(int u,int v){Edges[id].to = v;Edges[id].next = Head[u];Head[u] = id++;}void TarjanBFS(int pos,int from){Stack[m++] = pos;dfn[pos] = low[pos] = ++lay;for(int i = Head[pos]; i != -1; i = Edges[i].next){if(Edges[i].to == from)continue;if( !dfn[Edges[i].to] ){TarjanBFS(Edges[i].to,pos);low[pos] = min(low[pos],low[Edges[i].to]);//if( dfn[pos] < low[Edges[i].to] )//{//while(Stack[m–] != Edges[i].to);//}}elselow[pos] = min(low[pos],low[Edges[i].to]);}}int main(){int u,v;while(~scanf("%d%d",&N,&M)){memset(Head,-1,sizeof(Head));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(degree,0,sizeof(degree));m = lay = scc = id = 0;for(int i = 0; i < M; ++i){scanf("%d%d",&u,&v);AddEdges(u,v);AddEdges(v,u);}for(int i = 1; i <= N; ++i)if( !dfn[i] )TarjanBFS(1,-1);for(int i = 1; i <= N; ++i){for(int j = Head[i]; j != -1; j = Edges[j].next){if(low[i] != low[Edges[j].to])degree[low[i]]++;}}int ans = 0;for(int i = 1; i <= N; ++i)if(degree[i] == 1)ans++;printf("%d\n",(ans+1)/2);}return 0;}

经验是由痛苦中粹取出来的

POJ3352 Road Construction【边双联通分量】【Tarjan】

相关文章:

你感兴趣的文章:

标签云: