传送门(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. [Python3网络爬虫开发实战] 1.2.5-PhantomJS的安装

    PhantomJS是一个无界面的.可脚本编程的WebKit浏览器引擎,它原生支持多种Web标准:DOM操作.CSS选择器.JSON.Canvas以及SVG. Selenium支持PhantomJS,这 ...

  2. Python解释器的种类以及特点

    CPython 由C语言开发的  使用最广的解释器 IPython 基于cpython之上的一个交互式计时器 交互方式增强 功能和cpython一样 PyPy 目标是执行效率 采用JIT技术 对pyt ...

  3. LeetCode 123. Best Time to Buy and Sell Stock III (stock problem)

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  4. 易接SDK ios9以上无法弹出充值界面的一种情况

    充值需要用到http请求: 打开info.plist, 在app tansport security  setting 这个项 ,  加入  NSAllowsArbitraryLoads YES

  5. 九度oj 题目1063:整数和

    题目1063:整数和 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4043 解决:2638 题目描述: 编写程序,读入一个整数N.若N为非负数,则计算N到2N之间的整数和:若N为一个负数 ...

  6. zoj 2676 dinic模板求实型最小割(可做dinic模板)

    #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #inc ...

  7. codevs 3164 质因数分解

    3164 质因数分解  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description (多数据)给出t个数,求出它的质因子个 ...

  8. Java线程:Callable和Future

    接着上一篇继续并发包的学习,本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果.        Callable接口类似于Runnable,从名字就可以看出来了,但 ...

  9. css 實現微信聊天類似的氣泡

    要實現這樣的效果 代碼如下: --------------------------------------- <style> .test{width:300px; padding:30px ...

  10. has实现 更新视图但不重新加载页面原理

    URL中#符号本身以及它的字符称之为hash,可以通过window.location.hash获取.hash具有如下特点: 1.has虽然出现在URL中,但不会被包括在http请求中.因此,改变has ...