传送门(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. random,json,pickle,hashlib,shutil,hmac,shelve 模块

    一,复习 ''' 项目开发规范 ATM -- bin: 可执行文件 # run.py import os import sys BASE_DIR = os.path.dirname(os.path.d ...

  2. 笔记——collections模块

    collections模块 collections模块在内置数据类型(dict.list.set.tuple)的基础上,还提供了几个额外的数据类型:ChainMap.Counter.deque.def ...

  3. python之GUI图形用户界面 2014-4-7

    #图形用户界面1.下载和安装wxPython2.创建并显示一个框架import wx #导入wxPythonapp=wx.App()win=wx.Frame(None)win.Show() #调用窗口 ...

  4. C51 继电器 个人笔记

    一句话 小电流控制大电流的开关. 电路图 给J2端口一个低电平,三极管导通,线圈吸合 一般用P1^4口连接 #include <reg51.h> #define u16 unsigned ...

  5. codevs4439 YJQ Requires Food

    题目描述 Description 神犇YJQ有n个不同的妹子和m种食物,每一天每一种食物只供应一个妹子吃的份量.在接下来的t天内,YJQ准备包养所有的妹子. 对于每个妹子,她在t天内都只会吃某些特定的 ...

  6. POJ 3469_Dual Core CPU

    题意: N个模块可以在A,B两个核上运行,分别需要A[i]和B[i],模块之间需要传递数据,若两个模块在同一核上,则不需要花费,否则需要花费w[i].问最少需要花费多少? 分析: 用最小的费用将两个对 ...

  7. Layui选项卡、进度条、面板、徽章、时间线、辅助元素

    Layui选项卡.进度条.面板.徽章.时间线.辅助元素 Tab选项卡 - 页面元素    导航菜单可应用于头部和侧边,Tab选项卡提供多套风格,支持响应式,支持删除选项卡等功能.面包屑结构简单,支持自 ...

  8. <项目><day11>查看用户浏览过的商品

    <项目>查看用户浏览过的商品 1.创建一个entity包储存实体对象 1.1创建一个Product的类存储实体对象 对象具有以下属性,并添加set和get方法,含参和不含参的构造方法,to ...

  9. 安装adt-bundle-windows-x86-20130917时遇到的问题及解决方法

    最近在上安卓课,老师让我们下载此软件(adt-bundle-windows-x86-20130917.下载压缩后,打开eclipse的时候,会出现以下情况: 这时说明你的jdk还没下载或者下载错位置了 ...

  10. fetch各种报跨域错误,数据无法获取的解决方案

    1.介绍 fetch 提供了一个获取资源的接口 (包括跨域). fetch 的核心主要包括:Request , Response , Header , Body 利用了请求的异步特性 --- 它是基于 ...