HDU 4612 Warm up —— (缩点 + 求树的直径)
题意:一个无向图,问建立一条新边以后桥的最小数量。
分析:缩点以后,找出新图的树的直径,将这两点连接即可。
但是题目有个note:两点之间可能有重边!而用普通的vector保存边的话,用v!=fa的话是没办法让重边访问的,因此,使用数组模拟邻接表的方法来储存边。
这样,只要访问了一条边以后,令E[i].vis=E[i^1].vis=1即可,这样可以防止无向图的边和重边搞混。原理就是按位异或,一个奇数^1变为比它小1的偶数,反之亦然:如5^1=4,4^1=5。
具体见代码:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stack>
#include <vector>
#include <set>
#include <queue>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; const int N = +; int n,m,dfn[N],low[N];
int head[N];
int tot=;
int dfs_clock;
int bridge;
int belong[N];
int scc_cnt;
int maxd;
bool vis[N];
vector<int> G[N];
stack<int> S; struct edge
{
int v;
int vis;
int nxt;
}E[*+]; void addEdge(int u,int v)
{
E[tot].v=v;
E[tot].vis=;
E[tot].nxt=head[u];
head[u]=tot++; E[tot].v=u;
E[tot].vis=;
E[tot].nxt=head[v];
head[v]=tot++;
} void tarjan(int u)
{
dfn[u]=low[u]=++dfs_clock;
S.push(u);
for(int i=head[u];i!=-;i=E[i].nxt)
{
int v = E[i].v;
if(E[i].vis) continue;
E[i].vis=E[i^].vis=; if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]); if(low[v]>dfn[u]) bridge++;
}
else if(!belong[v])
{
low[u]=min(low[u],dfn[v]);
}
} if(dfn[u]==low[u])
{
scc_cnt++;
for(;;)
{
int x = S.top();S.pop();
belong[x] = scc_cnt;
if(x==u) break;
}
}
} void init()
{
memset(head,-,sizeof(head));
tot=;
memset(dfn,,sizeof(dfn));
dfs_clock=;
bridge=;
memset(belong,,sizeof(belong));
scc_cnt=;
maxd=;
for(int i=;i<=n;i++) G[i].clear();
memset(vis,,sizeof(vis));
} //找到树的直径
void findMaxDeep(int u,int deep)
{
vis[u]=; maxd=max(maxd,deep);
for(int i=;i<G[u].size();i++)
{
int v = G[u][i];
if(!vis[v])
{
findMaxDeep(v,deep+);
}
}
} //用bfs来找到一个叶子节点
int findRoot()
{
queue<int> Q;
Q.push();
vis[]=;
int last=;
while(!Q.empty())
{
int x = Q.front();Q.pop();
for(int i=;i<G[x].size();i++)
{
int v = G[x][i];
if(!vis[v])
{
Q.push(v);
vis[v]=;
last=v;
}
}
}
return last;
} void solve()
{
for(int i=;i<=n;i++) if(!dfn[i]) tarjan(i); //重新建图
for(int i=;i<=n;i++)
{
for(int j=head[i];j!=-;j=E[j].nxt)
{
int v = E[j].v;
int x = belong[i];
int y = belong[v];
if(x!=y)
{
G[x].push_back(y);
G[y].push_back(x);
}
}
} int root=findRoot();
memset(vis,,sizeof(vis)); findMaxDeep(root,); printf("%d\n",bridge-maxd);
} int main()
{
while(scanf("%d%d",&n,&m)==)
{
if(n== && m==) break;
init(); for(int i=;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v);
} solve();
}
}
但是奇怪的是,重新建图以后找叶子节点的时候,这里用G[x].size()==2不能够实现。讲道理,原理上是没错的,尽管后来发现如果缩点后只有一个点的话是个例外,但是即使排除了这个特殊情况仍然不行,,,这个问题也留着以后探讨吧。。
HDU 4612 Warm up —— (缩点 + 求树的直径)的更多相关文章
- 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。
问加一条边,最少可以剩下几个桥. 先双连通分量缩点,形成一颗树,然后求树的直径,就是减少的桥. 本题要处理重边的情况. 如果本来就两条重边,不能算是桥. 还会爆栈,只能C++交,手动加栈了 别人都是用 ...
- F - Warm up - hdu 4612(缩点+求树的直径)
题意:有一个无向连通图,现在问添加一条边后最少还有几个桥 分析:先把图缩点,然后重构图为一棵树,求出来树的直径即可,不过注意会有重边,构树的时候注意一下 *********************** ...
- HDU 4612 Warm up(双连通分量缩点+求树的直径)
思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...
- hdu4612 无向图中随意加入一条边后使桥的数量最少 / 无向图缩点+求树的直径
题意如上,含有重边(重边的话,俩个点就能够构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选随意起点U,进行bfs,到达最远的一个点v ...
- hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径
题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v ...
- (求树的直径)Warm up -- HDU -- 4612
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 给一个无向图, 加上一条边后,求桥至少有几个: 那我们加的那条边的两个顶点u,v:一定是u,v之 ...
- hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Su ...
- HDU 4612 Warm up (边双连通分量+缩点+树的直径)
<题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...
- HDU 4612——Warm up——————【边双连通分量、树的直径】
Warm up Time Limit:5000MS Memory Limit:65535KB 64bit IO Format:%I64d & %I64u Submit Stat ...
随机推荐
- hdu 2767 强连通缩点处理加边问题
#include <cstring> #include <cstdlib> #include <cstdio> 缩点的好处就是可以将乱七八糟的有向图 转化为无环的有 ...
- Scala学习十八——高级类型
一.本章要点 单例类型可用于方法串接和带对象参数的方法 类型投影对所有外部类的对象都包含了其他内部类的实例 类型别名给类型指定一个短小的名称 结构类型等效于”鸭子类型“ 存在类型为泛型的通配参数提供了 ...
- sql游标循环
DECLARE @begindate DATETIME=CONVERT(DATETIME, '2019.05.06 09:40:50') ,@enddate DATETIME =GETDATE() , ...
- luogu1005矩阵取数游戏题解--区间DP
题目链接 https://www.luogu.org/problemnew/show/P1005 分析 忽然发现这篇题解好像并没有什么意义...因为跟奶牛零食那道题一模一样,博主比较懒如果您想看题解的 ...
- arcgis js之卷帘工具
arcgis js之卷帘工具 效果图: 代码: var swipe = new Swipe({ view: view, leadingLayers: [layer1, layer2], trailin ...
- python+requests模拟登陆 学校选课系统
最近学校让我们选课,每天都有不同的课需要选....然后突发奇想试试用python爬学校选课系统的课程信息 先把自己的浏览器缓存清空,然后在登陆界面按f12 如图: 可以看到登陆时候是需要验证码的,验证 ...
- 如何部署自定义的servlet
1 首先找到与exlipse绑定的tomcat安装位置 2 打开web.xml添加如下信息: <display-name>servletDemo</display-name> ...
- Jmeter官方插件实现Dubbo接口测试
目前主流的分布式框架有Dubbo和SpringCloud, SpringCloud是基于Http协议的分布式框架,Dubbo是基于RPC的分布式框架,Jmeter没有内置对Dubbo接口的支持,很难直 ...
- PHPStorm 3.3 破解方法 以及汉化
第一步修改host文件(host文件地址为): C:\Windows\System32\drivers\etc 将以下内容添加到host文件里面 0.0.0.0 account.jetbrai ...
- PAT乙级1041
题目链接 https://pintia.cn/problem-sets/994805260223102976/problems/994805281567916032 题解 简单的信息录入和查询而已. ...