给一个无向图,问至少加入多少条边能够使图变成双连通图(随意两点之间至少有两条不同的路(边不同))。

图中的双连通分量不用管,所以缩点之后建新的无向无环图。

这样,题目问题等效于,把新图中度数为1的点相互连到图里面形成环

如果这种点有sum个,那么至少须要加入(sum+1)/2 条边。

下面,基本上就是求边双连通分量模板。

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define eps 1e-6
#define ll __int64
using namespace std;
#define N 5010
#define M 10010 struct node
{
int v,next,vis;
},e[M];
int h,head[N];
int belong[N],vis[N],dfn[N],low[N],brig[N][2],nbrig,col,cnt,top,in[N],sta[N];
int n,m; void addedge(int a,int b)
{
e[h].v=b;
e[h].vis=0;
e[h].next=head[a];
head[a]=h++;
} void tarjan(int u)
{
int v;
vis[u]=1;
dfn[u]=low[u]=++cnt;
sta[top++]=u;
for(int i=head[u];i!=-1;i=e[i].next)
{
if(e[i].vis) continue;
e[i].vis=e[i^1].vis=1;
v=e[i].v;
if(vis[v]==1)
low[u]=min(low[u],dfn[v]);
if(!vis[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])
{
brig[nbrig][0]=u;
brig[nbrig++][1]=v;
}
}
}
if(low[u]==dfn[u])
{
++col;
do
{
v=sta[--top];
vis[v]=0;
belong[v]=col;
}while(u!=v);
}
} void init()
{
memset(head,-1,sizeof head);
memset(vis,0,sizeof vis);
memset(belong,-1,sizeof belong);
h=h1=cnt=col=nbrig=top=0;
} int main()
{
int i,j,k,a,b;
while(~scanf("%d%d",&n,&m))
{
init();
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}
tarjan(1);
memset(in,0,sizeof in);//记度数//无向图
for(i=0;i<nbrig;i++)//缩点后 树的边是原图里的桥组成
{
a=brig[i][0];
b=brig[i][1];
if(belong[a]!=belong[b])
in[belong[a]]++,in[belong[b]]++;
}
int sum=0;
for(i=1;i<=col;i++)
if(in[i]==1) sum++;
printf("%d\n",(sum+1)/2);
}
return 0;
}

以下这个模板太龊。。

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define eps 1e-6
#define ll __int64
using namespace std;
#define N 1010
#define M 20010 struct node
{
int v;//下个顶点
node *next;//下个边结点
};
int n,m,r[N],d[N];//d表示缩点后各顶点的度数
node mem[M];int memp;//存储边结点
node *e[N];
int necc;//原图中边双连通分量的个数
int belong[N];
int low[N],dfn[N];
int vis[N];
int brig[M][2],nbrig; void addedge(int i,int j)
{
node *p=&mem[memp++];
p->v=j;
p->next=e[i];
e[i]=p;
} int root(int a)
{
if(a!=r[a])
r[a]=root(r[a]);
return r[a];
} void merge(int a,int b)
{
int ra=root(a);
int rb=root(b);
if(ra!=rb)
r[ra]=rb;
} void dfs(int i,int father,int dth)
{
int j,tofa=0;
node *p;
vis[i]=1;
low[i]=dfn[i]=dth;
for(p=e[i];p!=NULL;p=p->next)
{
j=p->v;
if(vis[j]&&(j!=father||tofa))
low[i]=min(low[i],dfn[j]);
if(!vis[j])
{
dfs(j,i,dth+1);
low[i]=min(low[i],low[j]);
if(low[j]<=dfn[i]) merge(i,j);//i,j在同一个双联通分量
if(low[j]>dfn[i]) //边i,j是桥
{
brig[nbrig][0]=i;
brig[nbrig++][1]=j;
}
}
if(j==father) tofa=1;
}
vis[i]=2;
} int doubleconne()
{
int i,k,ncon=nbrig=0;
dfs(0,-1,1);
for(i=0;i<n;i++)
{
k=root(i);
if(belong[k]==-1) belong[k]=ncon++;
belong[i]=belong[k];
}
return ncon;
} void init()
{
memp=nbrig=0;
memset(e,0,sizeof e);
memset(d,0,sizeof d);
for(int i=0;i<=n;i++)
r[i]=i;
memset(vis,0,sizeof vis);
memset(belong,-1,sizeof belong);
} int main()
{
int i,j,k,a,b;
while(~scanf("%d%d",&n,&m))
{
init();
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
addedge(a-1,b-1);
addedge(b-1,a-1);
}
necc=doubleconne();
for(k=0;k<nbrig;k++)
{
i=brig[k][0];
j=brig[k][1];
d[belong[i]]++;
d[belong[j]]++;
}
int cnt=0;//收缩后叶子结点的个数
for(i=0;i<necc;i++)
if(d[i]==1) cnt++;
printf("%d\n",(cnt+1)/2);
}
return 0;
}

poj3177 Redundant Paths 边双连通分量的更多相关文章

  1. POJ3177 Redundant Paths【双连通分量】

    题意: 有F个牧场,1<=F<=5000,现在一个牧群经常需要从一个牧场迁移到另一个牧场.奶牛们已经厌烦老是走同一条路,所以有必要再新修几条路,这样它们从一个牧场迁移到另一个牧场时总是可以 ...

  2. POJ3177 Redundant Paths —— 边双联通分量 + 缩点

    题目链接:http://poj.org/problem?id=3177 Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total ...

  3. [POJ3177]Redundant Paths(双联通)

    在看了春晚小彩旗的E技能(旋转)后就一直在lol……额抽点时间撸一题吧…… Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Tota ...

  4. [POJ3177]Redundant Paths(双连通图,割边,桥,重边)

    题目链接:http://poj.org/problem?id=3177 和上一题一样,只是有重边. 如何解决重边的问题? 1.  构造图G时把重边也考虑进来,然后在划分边双连通分量时先把桥删去,再划分 ...

  5. poj 3177 Redundant Paths(边双连通分量+缩点)

    链接:http://poj.org/problem?id=3177 题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任 ...

  6. POJ3177 Redundant Paths 双连通分量

    Redundant Paths Description In order to get from one of the F (1 <= F <= 5,000) grazing fields ...

  7. POJ3177 Redundant Paths(边双连通分量+缩点)

    题目大概是给一个无向连通图,问最少加几条边,使图的任意两点都至少有两条边不重复路径. 如果一个图是边双连通图,即不存在割边,那么任何两个点都满足至少有两条边不重复路径,因为假设有重复边那这条边一定就是 ...

  8. poj3352 Road Construction & poj3177 Redundant Paths (边双连通分量)题解

    题意:有n个点,m条路,问你最少加几条边,让整个图变成边双连通分量. 思路:缩点后变成一颗树,最少加边 = (度为1的点 + 1)/ 2.3177有重边,如果出现重边,用并查集合并两个端点所在的缩点后 ...

  9. POJ3177 Redundant Paths 图的边双连通分量

    题目大意:问一个图至少加多少边能使该图的边双连通分量成为它本身. 图的边双连通分量为极大的不存在割边的子图.图的边双连通分量之间由割边连接.求法如下: 求出图的割边 在每个边双连通分量内Dfs,标记每 ...

随机推荐

  1. React 中组件的生命周期

    先上代码, react 用的是 15.0.1 <!DOCTYPE html> <html> <head> <script src="./build/ ...

  2. Meeting Rooms II -- LeetCode

    Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si ...

  3. 使用create-react-app时的something is already running on port 3000

    问题: 自己今天在使用create-react-app搭建react应用的时候,开启了两个React app,然后npm start的时候,出现something is already running ...

  4. Highcharts做统计图。

    <script> $(function () { var areasplineData = [[1447916401000,3],[1447918201000,4]]; var typeR ...

  5. Spring MVC常用注解@PathVariable、@RequestHeader、@CookieValue、@RequestParam、@RequestBody、@SessionAttributes、@ModelAttribute

    简介: handler method参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型) A.处理requet uri部分(这里指uri template中 ...

  6. Python 学习建议(个人愚见)

    前言 本科毕业已经5年+,一直在做iOS开发. 工作方面:从刚入门的小菜鸟码农,后面到BAT里混过两年,到现在带10个人的Team Leader,收入尚可. 生活状态:已婚,儿子刚满1岁,有一定存款, ...

  7. JS 的一些基础算法题

    1.翻转字符串   例子(要求:先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序,最后把数组转化成字符串) function reverseString(str) { str=str. ...

  8. 定制你自己的CRF模型

    如何训练自己的CRF模型 Ansj从5.0版本之后支持训练自己的crf模型,在此之前虽然已经很早支持了CRF模型,但是在用户的自训练上要求苛刻,而且本身实现的CRF从性能到准确率都不如CRF++或者第 ...

  9. 预防U盘被病毒侵害的方法

    写在前面:此方法只能杜绝自己的u盘免收侵害,而不能杜绝自己的电脑免收其他u盘病毒的侵害,如果想知道如何让自己的电脑防止被u盘病毒侵害,可以阅读此文章:https://www.cnblogs.com/t ...

  10. 有关ubuntu16.04进行sudo apt-get update更新时出现:‘。。。N: 无法安全地用该源进行更新,所以默认禁用该源。。。’等问题解决方案

    关于ubuntu16.04在 sudo apt-get update 时出现如下错误: 针对这种情况,本人结合网上的解决方案总结出以下方案,三条命令搞定,希望有用. 1. 进入 sources.lis ...