传送门(poj3177)

这道题是Tarjan求桥的模板题。大意是要求在原图上加上数量最少的边,使得整张图成为一个边双联通分量。

具体的做法是,先在图中求出所有的桥,之后把边双联通分量缩成点,这样的话原图就变成了一棵树。之后,我们就在叶子之间加边即可。如何加最少的边呢?好像第一眼看上去,随便在两个叶子中间加一条边就能减少两个叶子,但事实上不是这样的,如果这两个叶子中间的路径数小于等于1条的话,将新形成的边双联通分量缩点之后有可能出现新的叶子。就像这张图一样,如果连接红色的边,那么新的图会多出一个叶子。

这个是因为路径上的边数只有一条,如果我们选择两点路径上边数大于1的两个叶子合并,那么一定会形成一个新的边双联通分量,而且不会有新的叶子。

因为这样的话那个新的边双肯定是至少有两个度的,那他就不会成为叶子,而如果只有一条的话,它的度就是1,那么就形成新的叶子了。

我们要这样去合并:

这样就可以啦!所以我们最后能得出的结论就是,需要加的边数=(叶子个数+1) >> 1.

那我们直接求桥,之后缩点,求出每个点最后的度然后计算一下就行。

然后这题因为有重边就很难受……一开始我是直接判断如果是父亲就不管,但是这样不行……因为有重边的就不是桥了,他是需要父亲去更新的,所以后来判断一下,只有树边的那条反向边我们给他特判掉,其他的都能正常更新。

看一下代码。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define pr pair<int,int>
#define mp make_pair
#define fi first
#define sc second
using namespace std;
typedef long long ll;
const int M = ;
const int N = ; int read()
{
int ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >='' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
} struct edge
{
int next,to,from;
}e[M]; int f,r,x,y,ecnt = -,head[M],dfn[M],low[M],scc[M],stack[M],top,cnt,rdeg[M],ans,idx;
bool vis[M],pd[M]; void add(int x,int y)
{
e[++ecnt].to = y;
e[ecnt].from = x;
e[ecnt].next = head[x];
head[x] = ecnt;
} void tarjan(int x,int g)
{
bool flag = ;
vis[x] = ,stack[++top] = x;
dfn[x] = low[x] = ++idx;
for(int i = head[x];~i;i = e[i].next)
{
//if(pd[i]) continue;
//pd[i] = pd[i^1] = 1;
if(e[i].to == g && !flag)
{
flag = ;
continue;
}
if(!dfn[e[i].to]) tarjan(e[i].to,x),low[x] = min(low[x],low[e[i].to]);
else if(vis[e[i].to])low[x] = min(low[x],dfn[e[i].to]);
}
if(low[x] == dfn[x])
{
int p;
cnt++;
while((p = stack[top--]))
{
scc[p] = cnt,vis[p] = ;
if(p == x) break;
}
}
} int main()
{
memset(head,-,sizeof(head));
f = read(),r = read();
rep(i,,r) x = read(),y = read(),add(x,y),add(y,x);
rep(i,,f) if(!dfn[i]) tarjan(i,i);
rep(i,,f)
{
for(int j = head[i];~j;j = e[j].next)
{
int r1 = scc[e[j].to],r2 = scc[i];
if(r1 != r2) rdeg[r1]++,rdeg[r2]++;
}
}
rep(i,,cnt) if(rdeg[i] == ) ans++;
printf("%d\n",(ans+) >> );
return ;
}

Tarjan求桥的更多相关文章

  1. Tarjan 求桥,割,强连通

    最近遇到了这种模板题,记录一下 tarjan求桥,求割 #include <bits/stdc++.h> using namespace std; #define MOD 99824435 ...

  2. tarjan求桥、割顶

    若low[v]>dfn[u],则(u,v)为割边.但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理.我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父 ...

  3. hdu 4738 Caocao's Bridges (tarjan求桥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738 题目大意:给一些点,用一些边把这些点相连,每一条边上有一个权值.现在要你破坏任意一个边(要付出相 ...

  4. Codeforces 700 C. Break Up(Tarjan求桥)

    题意 给你一个有 \(n\) 个点, \(m\) 条边的无向图,每条有边权 \(w_i\) ,现在要选择至多两条边断开,使得 \(S, T\) 不连通,并且使得边权和尽量小. \(n \le 1000 ...

  5. UVA 796 Critical Links(Tarjan求桥)

    题目是PDF就没截图了 这题似乎没有重边,若有重边的话这两点任意一条边都不是桥,跟求割点类似的原理 代码: #include <stdio.h> #include <bits/std ...

  6. UVA796 - Critical Links(Tarjan求桥)

    In a computer network a link L, which interconnects two servers, is considered critical if there are ...

  7. HDU-4612 Warm up,tarjan求桥缩点再求树的直径!注意重边

    Warm up 虽然网上题解这么多,感觉写下来并不是跟别人竞争访问量的,而是证明自己从前努力过,以后回头复习参考! 题意:n个点由m条无向边连接,求加一条边后桥的最少数量. 思路:如标题,tarjan ...

  8. uva 796 C - Critical Links(tarjan求桥)

    题目链接:https://vjudge.net/contest/67418#problem/C 题意:求出桥的个数并且按顺序输出 题解:所谓桥就是去掉这条边后连通块增加,套用一下模版就行. #incl ...

  9. HDU 4738 Caocao's Bridges(Tarjan求桥+重边判断)

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

随机推荐

  1. buf.swap32()

    buf.swap32() 返回:{Buffer} 将 Buffer 解释执行为一个32位的无符号整数数组并以字节顺序交换到位.如果 Buffer 的长度不是32位的倍数,则抛出一个 RangeErro ...

  2. Python之使用eval()函数将字符串的数据结构提取出来

    data = input('请输入你要修改的对象:').strip() ''' 输入下面的字典列表 [{'backend':'www.oldboy1.org','record':{'server':' ...

  3. ARM中的---汇编指令

    一. 带点的(一般都是ARM GNU伪汇编指令) 1. ".text".".data".".bss" 依次表示的是"以下是代码段& ...

  4. FPGA学习笔记(六)—— 时序逻辑电路设计

    用always@(posedge clk)描述        时序逻辑电路的基础——计数器(在每个时钟的上升沿递增1) 例1.四位计数器(同步使能.异步复位) // Module Name: coun ...

  5. 56. spring boot中使用@Async实现异步调用【从零开始学Spring Boot】

    什么是"异步调用"? "异步调用"对应的是"同步调用",同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执 ...

  6. 启的服务有时候突然报错:org.xml.sax.SAXParseException: schema_reference.4

    记录一下,原文地址:http://blog.csdn.net/bluishglc/article/details/7596118

  7. DRF:过滤&搜索&排序功能

    过滤功能利用的是第三方包 django_filters,搜索和排序利用的是 Django DRF 提供的 filters 示例代码如下: from rest_framework import filt ...

  8. 接龙游戏(codevs 1051)

    1051 接龙游戏  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 给出了N个单词,已经按长度排好了序 ...

  9. Count Color POJ - 2777 线段树

    Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds ...

  10. JSP发送电子邮件

    以下内容引用自http://wiki.jikexueyuan.com/project/jsp/sending-email.html: 发送一个简单的电子邮件 给出一个简单的例子,从机器上发送一个简单的 ...