【边双连通 && 树的直径】HDU
来源:互联网 发布:百度云管家mac版 编辑:程序博客网 时间:2024/05/16 15:09
Problem Description
输入n,m代表有n个点,有m条边。有重边,这里重边指的是1-2,1-2如果出现了两次,代表1-2有两条不同的道路接下面m行,每行u,v代表u-v有一条道路(双向)。问你加一条边,最少还剩下多少个桥
思路:
树的直径参考:http://blog.csdn.net/Triple_WDF/article/details/50118115 将图按双连通分量缩点后,桥的数量-直径的长度 就是结果。
有重边所以得特殊处理下,1-2,2-1如果是同一条边,那么1到2后 2不能到1。如果不是同一条边1-2后,2可以到1。所以求双连通分量的时候判断一下是不是同一条边就可以了
#include<bits/stdc++.h>using namespace std;#define mm 1000055#define nn 200055struct node{ int to, next;};node Map[2 * mm];//前向星存图int head[nn], low[nn], dfn[nn], vis[nn], top, sig, N, Stack[nn];//vis[i]代表i属于vis[i]这个双连通分量int n, vv[nn], d, flag;node MAP[mm];int cc;void add(int u, int v, int &cnt)//相邻的cnt奇偶是同一条边,例如0,1是同一条边 奇数^1 为偶数(奇数-1) 偶数^1 为 奇数(偶数+1).所以相当于同一条边{ Map[cnt].to = v; Map[cnt].next = head[u]; head[u] = cnt++;}void tardfs(int u, int father){ low[u] = dfn[u] = sig++; Stack[top++] = u; for(int i = head[u]; ~i; i = Map[i].next) { int to = Map[i].to; if(!dfn[to]) { tardfs(to, i); low[u] = min(low[u], low[to]); if(low[to] > dfn[u])//记录割边两端的的点 { MAP[cc].to = u; MAP[cc++].next = to; } } else if(!vis[to] && i != (father ^ 1))//不是同一条边 { low[u] = min(low[u], dfn[to]); } } if(low[u] == dfn[u])//缩点 { N++; do { int t = Stack[top - 1]; vis[t] = N; top--; }while(Stack[top] != u); }}void tarjan(){ top = 0, sig = 1, N = 0; memset(vis, 0, sizeof(vis));//初始化 memset(dfn, 0, sizeof(dfn)); for(int i = 1; i <= n; i++) { if(!vis[i]) tardfs(i, i); }}void dfs(int u){ for(int i = head[u]; ~i; i = Map[i].next) { int to = Map[i].to; if(!vv[to]) { vv[to] = vv[u] + 1; if(vv[to] > d) { d = vv[to]; flag = to; } dfs(to); } }}int main(){ int m, u, v; while(~scanf("%d %d", &n, &m)) { if(!n && !m) break; int cnt = 0;//初始化 memset(head, -1, sizeof(head)); while(m--) { scanf("%d %d", &u, &v); add(u, v, cnt);//双向 add(v, u, cnt); } cc = 0; tarjan();//缩点,求双连通分量 cnt = 0; memset(head, -1, sizeof(head)); for(int i = 0; i < cc; i++)//按照缩点后,建图 { u = MAP[i].to, v = MAP[i].next; if(vis[u] != vis[v]) { add(vis[u], vis[v], cnt); add(vis[v], vis[u], cnt); } } memset(vv, 0, sizeof(vv));//两次dfs求树的直径 vv[1] = 1; d = 1; flag = 1; dfs(1); memset(vv, 0, sizeof(vv)); vv[flag] = 1; d = 1; dfs(flag); printf("%d\n", cc - d + 1); }}
阅读全文
0 0
- 【边双连通 && 树的直径】HDU
- HDU 4612 Warm up 边双连通+树的直径
- hdu 4612 Warm up(边-双连通+缩点+树的直径)
- HDU 4612 Warm up(边双连通、树的直径)
- hdu 4612 Warm up 双连通缩点+树的直径
- Hdu 4612 Warm up (双连通缩点+树的直径)
- HDU 4612 Warm up(边双连通分量+树的直径)
- hdu 4612 Warm up 边双连通分量+树的直径
- HDU 4612--Warm up 【无向图边双连通求桥数 && 缩点后重建图求树的直径】
- hdu 4612 tarjian求桥双连通分量缩点+树直径
- hdoj 4612 Warm up 【无向图边双连通求桥数 缩点后求树的直径 桥数-树的直径】
- hdu4612 Warm up(边双连通缩点+树的直径)
- hdu 3721 树的直径
- HDU 4607 树的直径
- HDU 2196 树的直径
- 树的直径 hdu 4607
- 树的直径 hdu 2196
- hdu 4005(边双连通)
- Android 智能指针学习笔记(二,完结) —— 强指针,弱指针
- 上一篇先鸽了,用到的时候再填坑,这篇马一下meshlab的安装
- eclipse启动不了服务器
- 大数据预科班12
- 关于压缩感知的第一篇论文解析压缩感知研究新思路
- 【边双连通 && 树的直径】HDU
- SGISTL源码探究-STL中的hashtable(上)
- [BZOJ]1056 和 1862 splay
- windows performance monitor
- android64位机器兼容32位.so库文件
- java标识符与关键
- 略仿今日头条部分功能,只供参考,娱乐而已(图片3秒跳转,无限轮播,webview,tablayout,listview,Xlistview)
- 阿里云Linux环境安装之JDK
- poi自动调整宽度