hdu 4612 求边连通分量+求树的直径
来源:互联网 发布:苹果ios7是什么软件 编辑:程序博客网 时间:2024/04/29 20:47
http://acm.hdu.edu.cn/showproblem.php?pid=4612
题意:
加一条边,使得桥的数量最少?
思路:
求边连通分量,缩点,然后变成一个树,树边都是桥,求树的直径。
树的直径就是最多减少的桥。
桥的数量最少就是原图中的桥的数量 - 树的直径。
要注意重边。
#pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>using namespace std;typedef pair<int,int> pii;const int M_node = 200009, M_edge = 2000009;int low[M_node],dfn[M_node],belong[M_node],head[M_node];int dfs_clock,block,bridge,tot;int n,m,maxlen,s;bool instack[M_node];struct Node{ int u,v;}node[M_edge];struct edge{ int to,next; bool cut; bool mul;}edge[M_edge];vector<int> G[M_node];stack<int> st;void init(){ memset(head,-1,sizeof(head)); dfs_clock = block = bridge = tot = 0;}void add_edge(int u,int v,bool mul){ edge[tot].to = v; edge[tot].next = head[u]; edge[tot].cut = false; edge[tot].mul = mul; head[u] = tot++;}void tarjan(int u,int fa,bool mul){ low[u] = dfn[u] = ++dfs_clock; st.push(u); instack[u] = true; for(int i = head[u]; i != -1;i = edge[i].next) { int v = edge[i].to; if(v == fa && !mul) continue; //如果不是重边才跳过 if(!dfn[v]) { tarjan(v,u,edge[i].mul); low[u] = min(low[v],low[u]); if(low[v] > dfn[u]) { bridge++; edge[i].cut = true; edge[i^1].cut = true; } } else if(instack[u] && low[u] > dfn[v]) low[u] = dfn[v]; } if(low[u] == dfn[u]) { block++; for(;;) { int v = st.top(); st.pop(); instack[v] = false; belong[v] = block; if(v == u) break; } }}void dfs(int u,int pre,int len){ if(maxlen < len) { s = u; maxlen = len; } for(int i = 0; i < G[u].size();i++) { int v = G[u][i]; if(v == pre) continue; dfs(v,u,len+1); }}void solve(){ while(!st.empty()) st.pop(); memset(dfn,0,sizeof(dfn)); memset(instack,false,sizeof(instack)); tarjan(1,-1,false); for(int i = 1;i <= block;i++) G[i].clear(); for(int i = 1;i <= n;i++) { for(int j = head[i];j != -1;j = edge[j].next) { if(edge[j].cut) { //printf("debug -- i = %d , belong[i] = %d , edge[j].to = %d , belong[edge[j].to] = %d\n",i,belong[i],edge[j].to,belong[edge[j].to]); G[belong[i]].push_back(belong[edge[j].to]); } } } maxlen = -1; dfs(1,-1,0); maxlen = -1; dfs(s,-1,0); printf("%d\n",bridge - maxlen);}bool cmp(Node a,Node b){ if(a.u == b.u) return a.v < b.v; return a.u < b.u;}int main(){ while(scanf("%d %d",&n,&m) == 2) { init(); if(n == 0 && m == 0) break; for(int i = 0;i < m;i++) { int a,b; scanf("%d %d",&a,&b); if(a == b) continue; if(a > b) swap(a,b); node[i].u = a; node[i].v = b; } sort(node,node+m,cmp); for(int i = 0;i < m;i++) { if(i == 0 || (node[i].u != node[i-1].u || node[i].v != node[i-1].v)) { if(i < m - 1 && node[i].u == node[i+1].u && node[i].v == node[i+1].v) { add_edge(node[i].u,node[i].v,true); add_edge(node[i].v,node[i].u,true); } else { add_edge(node[i].u,node[i].v,false); add_edge(node[i].v,node[i].u,false); } } } solve(); } return 0;}
0 0
- hdu 4612 求边连通分量+求树的直径
- HDU 4612 Warm up (强连通,求树的直径)
- HDU 4612(缩点+求桥+求树的直径)
- 求图的连通分量
- hdu 1232 并查集 求连通分量的个数
- 强连通分量 求每个连通分量的最小值 hdu 1827
- hdu 1241 dfs求连通分量个数
- hdu 4587 (求强连通分量)
- HDU 3836 tarjan求强连通分量
- hdu 4607 求树的直径
- 求连通分量
- 求连通分量(深搜)
- 求连通分量
- 求连通分量
- 求连通分量(DFS)
- 求连通分量
- 求连通分量
- 求连通分量
- springcloud(第四篇)springcloud hystrix
- 块设备驱动程序(Linux设备驱动程序)
- LeetCode---Palindrome Number解题分析
- Yii表单的使用
- 5分钟学会双拼 双拼输入法 最简单的双拼入门教学 图文教程
- hdu 4612 求边连通分量+求树的直径
- IO学习(十三)使用带可变参数的方法关闭IO流
- Search for a Range
- Execution failed for task ':app:mergeDebugResources
- Linux中执行shell脚本的4种方法总结
- 牧场物语
- C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制构造函数,赋值操作符,析构函数)
- Unity两个物体发生碰撞的条件
- redis集群搭建之二~使用redis-trib.rb方法