poj3177
2016-07-19 21:56
148 查看
POJ3177
描述
为了从F(1≤F≤5000)个牧场(从1到F进行编号)中的一个到达另一个牧场,Bessie和他的牛只能穿过烂苹果林。这些牛现在都累了,不想老走这个特殊的小路而是想要建一些新的小路,这样它们就有至少两种选择在任意牧场之间穿梭。在任意的两个牧场之间,它们现在至少有一条路径而他们想要至少有2条路径。
现在给出建好的R(F-1≤R≤10000)条路,每条都连接了两个不同的牧场,确定新修道路的最小数量(每个也是连接两个牧场)使得任意两个牧场之间都能有两条路连通。道路都是不同的,不会有相同的小路,即使他们在沿路的中间会碰到相同的牧场。
这里可能已经有一对牧场有超过一条小路的,并且你可能也会修一条新的另外的小路来连接相同的牧场。
输入
第一行:两个空格隔开的整数:F和R
第二到第R+1行:每行包括两个空格隔开的整数,表示一些小路端点所在的牧场。
输出
第一行:一个单独的整数,表述新修小道的数量
样例输入
7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7
样例输出
2
提示
例子的解释:
一个形象化的小路:
1 2 3
+—+—+
| |
| |
6 +—+—+ 4
/ 5
/
/
7 +
建一个从1到6和从4到7的新路可以满足条件。
1 2 3
+—+—+
| |
| |
6 +—+—+ 4
/ 5 :
/ :
/ :
7 + - - - -
检查一些路径:
1 – 2: 1 –> 2 and 1 –> 6 –> 5 –> 2
1 – 4: 1 –> 2 –> 3 –> 4 and 1 –> 6 –> 5 –> 4
3 – 7: 3 –> 4 –> 7 and 3 –> 2 –> 5 –> 7
可以看出每对牧场都是由两条路连接的
有可能加一些别的下路也能解决这个问题(比如6到7加一条道)。然而加两条已经是最小了。
。。。。我根本没看懂提示的样子,还好知道这是构建双联通分量的题目,
首先求出所有的桥,然后删除这些桥边,剩下的每个连通块都是一个双连通子图。把每个双连通子图收缩为一个顶点,再把桥边加回来,最后的这个图一定是一棵树,边连通度为1。
统计出树中度为1的节点的个数,即为叶节点的个数,记为leaf。则至少在树上添加(leaf+1)/2条边,就能使树达到边二连通,所以至少添加的边数就 是(leaf+1)/2
嗯,这些话不是我说的;
4000
描述
为了从F(1≤F≤5000)个牧场(从1到F进行编号)中的一个到达另一个牧场,Bessie和他的牛只能穿过烂苹果林。这些牛现在都累了,不想老走这个特殊的小路而是想要建一些新的小路,这样它们就有至少两种选择在任意牧场之间穿梭。在任意的两个牧场之间,它们现在至少有一条路径而他们想要至少有2条路径。
现在给出建好的R(F-1≤R≤10000)条路,每条都连接了两个不同的牧场,确定新修道路的最小数量(每个也是连接两个牧场)使得任意两个牧场之间都能有两条路连通。道路都是不同的,不会有相同的小路,即使他们在沿路的中间会碰到相同的牧场。
这里可能已经有一对牧场有超过一条小路的,并且你可能也会修一条新的另外的小路来连接相同的牧场。
输入
第一行:两个空格隔开的整数:F和R
第二到第R+1行:每行包括两个空格隔开的整数,表示一些小路端点所在的牧场。
输出
第一行:一个单独的整数,表述新修小道的数量
样例输入
7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7
样例输出
2
提示
例子的解释:
一个形象化的小路:
1 2 3
+—+—+
| |
| |
6 +—+—+ 4
/ 5
/
/
7 +
建一个从1到6和从4到7的新路可以满足条件。
1 2 3
+—+—+
| |
| |
6 +—+—+ 4
/ 5 :
/ :
/ :
7 + - - - -
检查一些路径:
1 – 2: 1 –> 2 and 1 –> 6 –> 5 –> 2
1 – 4: 1 –> 2 –> 3 –> 4 and 1 –> 6 –> 5 –> 4
3 – 7: 3 –> 4 –> 7 and 3 –> 2 –> 5 –> 7
可以看出每对牧场都是由两条路连接的
有可能加一些别的下路也能解决这个问题(比如6到7加一条道)。然而加两条已经是最小了。
。。。。我根本没看懂提示的样子,还好知道这是构建双联通分量的题目,
首先求出所有的桥,然后删除这些桥边,剩下的每个连通块都是一个双连通子图。把每个双连通子图收缩为一个顶点,再把桥边加回来,最后的这个图一定是一棵树,边连通度为1。
统计出树中度为1的节点的个数,即为叶节点的个数,记为leaf。则至少在树上添加(leaf+1)/2条边,就能使树达到边二连通,所以至少添加的边数就 是(leaf+1)/2
嗯,这些话不是我说的;
#include<cstdio> #include<cstdlib> #include<cstring> struct edge{int v,next;}e[10010]; int n,en,t=0,index,m,a,b,vi; int dfn[5005],low[5005],scc[5005],first[5005];//scc记录缩点后个点的各种度(出度+入度) void addedge(int a, int b) { e[en].v = b; e[en].next = first[a]; first[a] = en++; } void clean() { memset(scc,0,sizeof(scc)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(first,-1,sizeof(first)); index=en=0; } void tarjan(int rt, int fa) { dfn[rt] = low[rt] = ++ index; for (int i =first[rt]; i != -1; i = e[i].next) { vi = e[i].v; if (!dfn[vi]) { tarjan(vi, rt); low[rt] = low[rt]<low[vi]?low[rt]:low[vi]; } else if (vi != fa) { low[rt] = low[rt]<dfn[vi]?low[rt]:dfn[vi]; } }//这里好像是照抄的上一题的。。 } void out() { for (int i = 1; i <= n; ++ i) { for (int j = first[i]; j != -1; j = e[j].next) { vi = e[j].v; if (low[vi] != low[i]) { //如果把所有的桥边删掉,剩下的可以化成一个个点 //只有被桥边分开的联通分量low值不同,看作两个不同的点 //但这本身又有一条边,于是这是桥边,两个联通分量的度加一 //应该是遍历时 另一个点也会遍历到这条边,所以每次自己加一就够了 scc[low[i]] ++; }//好六啊,反正不是我能想出来的 } } for (int i = 1; i <= n; ++ i) { if (scc[i] == 1) { t ++;//如果有度为1的,记录下来,给他们每个连一条边,就成了双联通 } } printf("%d\n", (t + 1) / 2);//先是他们之间互联 } int main() { clean(); scanf("%d %d", &n, &m) ; for (int i = 1; i <=m; ++ i) {scanf("%d %d", &a, &b);addedge(a,b);addedge(b,a);}//多么有爱的输入 tarjan(1, 1); out(); //这代码写时又让我欲仙欲死,在和ppt 网上的代码对比之后确定了算法没问题,但就是结果错了 //最后把网上的代码改成我的一步步纠错,却是把所有的i都加了一个int //嗯,大概是全局变量在各个函数调用的过程中死掉了 return 0; }
4000
相关文章推荐
- tarjan求割点
- 图论-割点数目
- 基于DFS求无向图的割点及桥(割边)算法总结 POJ_1144题解
- POJ 1144 / ZOJ 1311 : Network - 割点个数
- 无向图的割点(关节点)
- poj1144
- ACM学习-自己写割点
- poj 1523 SPF 求割点
- HDU 4738 Caocao's Bridges(双联通分量+并查集)
- HDU 3394 Railway (点双联通+圈内判边数)
- Network
- POJ 1144 Network
- 割点算法模板(Cut-vertex)
- poj_1144/uva_315/zoj_1311 Network(割點模板題)
- HDU 4587 Two Nodes、POJ 2375 Reliable Nets (Tarjan)
- 【研究总结】连通性问题
- 【图论算法及模版】割点,割边,强联通分量,点双联通分量,边双联通分量
- POJ 1523 SPF
- poj1144Network 无向图求割点Tarjan
- poj1523(割点)