算法笔记_149:图论之桥的应用(Java)
目录
1 问题描述
1310 One-way traffic
In a certain town there are n intersections connected by two- and one-way streets. The town is very
modern so a lot of streets run through tunnels or viaducts. Of course it is possible to travel between
any two intersections in both ways, i.e. it is possible to travel from an intersection a to an intersection
b as well as from b to a without violating traffic rules. Because one-way streets are safer, it has been
decided to create as much one-way traffic as possible. In order not to make too much confusion it has
also been decided that the direction of traffic in already existing one-way streets should not be changed.
Your job is to create a new traffic system in the town. You have to determine the direction of
traffic for as many two-way streets as possible and make sure that it is still possible to travel both ways
between any two intersections.
Write a program that:
• reads a description of the street system in the town from the standard input,
• for each two-way street determines one direction of traffic or decides that the street must remain
two-way,
• writes the answer to the standard output.
Input
The first line of the input contains two integers n and m, where 2 ≤ n ≤ 2000 and n−1 ≤ m ≤ n(n−1)/2.
Integer n is the number of intersections in the town and integer m is the number of streets.
Each of the next m lines contains three integers a, b and c, where 1 ≤ a ≤ n, 1 ≤ b ≤ n, a ̸= b and
c belongs to {1, 2}. If c = 1 then intersections a and b are connected by an one-way street from a to
b. If c = 2 then intersections a and b are connected by a two-way street. There is at most one street
connecting any two intersections.
Output
The output contains exactly the same number of lines as the number of two-way streets in the input.
For each such street (in any order) the program should write three integers a, b and c meaning, the new
direction of the street from a to b (c = 1) or that the street connecting a and b remains two-way (c = 2).
If there are more than one solution with maximal number of one-way streets then your program should
output any of them but just one.
Sample Input
4 4
4 1 1
4 2 2
1 2 1
1 3 2 Sample Output
2 4 1
3 1 2
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4056
2 解决方案
首先看看关于图论的割点和桥的相关概念定义:
引用文末参考资料1:
1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点。2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合。3.点连通度:最小割点集合中的顶点数。4.割边(桥):删掉它之后,图必然会分裂为两个或两个以上的子图。5.割边集合:如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合。6.边连通度:一个图的边连通度的定义为,最小割边集合中的边数。7.缩点:把没有割边的连通子图缩为一个点,此时满足任意两点之间都有两条路径可达。注:求块<>求缩点。缩点后变成一棵k个点k-1条割边连接成的树。而割点可以存在于多个块中。8.双连通分量:分为点双连通和边双连通。它的标准定义为:点连通度大于1的图称为点双连通图,边连通度大于1的图称为边双连通图。通俗地讲,满足任意两点之间,能通过两条或两条以上没有任何重复边的路到达的图称为双连通图。无向图G的极大双连通子图称为双连通分量。
具体代码如下:
package com.liuzhen.practice; import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack; public class Main {
public static int n; //给定图的顶点数
public static int count; //记录遍历次序
public static int[] DFN;
public static int[] Low;
public static int[] parent; //parent[i] = j,表示顶点i的直接父母顶点为j
public static Stack<Integer> stack;
public static ArrayList<edge>[] map;
public static ArrayList<edge> ans; //存储最终输出结果 static class edge {
public int a; //边的起点
public int b; //边的终点
public int c; //c = 1表示单向边,c = 2表示双向边 public edge(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
} @SuppressWarnings("unchecked")
public void init() {
count = 0;
DFN = new int[n + 1];
Low = new int[n + 1];
parent = new int[n + 1];
stack = new Stack<Integer>();
map = new ArrayList[n + 1];
ans = new ArrayList<edge>();
for(int i = 1;i <= n;i++) {
DFN[i] = -1;
Low[i] = -1;
parent[i] = -1;
map[i] = new ArrayList<edge>();
}
} public void TarJan(int start, int father) {
DFN[start] = count++;
Low[start] = DFN[start];
parent[start] = father;
stack.push(start);
for(int i = 0;i < map[start].size();i++) {
edge temp = map[start].get(i);
int j = temp.b;
if(DFN[j] == -1) {
TarJan(j, start);
Low[start] = Math.min(Low[start], Low[j]);
if(temp.c == 2) {
if(Low[j] > DFN[start]) { //当边temp为割边(或者桥)时
ans.add(temp);
} else {
ans.add(new edge(temp.a, temp.b, 1));
}
}
} else if(j != parent[start]) { //当j不是start的直接父母节点时
Low[start] = Math.min(Low[start], DFN[j]);
if(temp.c == 2) {
ans.add(new edge(temp.a, temp.b, 1));
}
}
}
} public void getResult() {
for(int i = 1;i <= n;i++) {
if(parent[i] == -1)
TarJan(i, 0);
}
for(int i = 0;i < ans.size();i++)
System.out.println(ans.get(i).a+" "+ans.get(i).b+" "+ans.get(i).c);
} public static void main(String[] args) {
Main test = new Main();
Scanner in = new Scanner(System.in);
n = in.nextInt();
int k = in.nextInt();
test.init();
for(int i = 0;i < k;i++) {
int a = in.nextInt();
int b = in.nextInt();
int c = in.nextInt();
map[a].add(new edge(a, b, c));
if(c == 2)
map[b].add(new edge(b, a, c));
}
test.getResult();
}
}
运行结果:
4 4
4 1 1
4 2 2
1 2 1
1 3 2
2 4 1
1 3 2
参考资料:
2. uva 1310 - One-way traffic(连通分量)
算法笔记_149:图论之桥的应用(Java)的更多相关文章
- 算法笔记_150:图论之双连通及桥的应用(Java)
目录 1 问题描述 2 解决方案 1 问题描述 Description In order to get from one of the F (1 <= F <= 5,000) graz ...
- 算法笔记_180:历届试题 国王的烦恼(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛.两个小岛间可能存在多座桥连接.然而,由于海水冲 ...
- 算法笔记_139:二分图的最大权匹配(Java)
目录 1 问题描述 2 解决方案 1 问题描述 何为二分图的最大权匹配问题? 最大权二分匹配问题就是给二分图的每条边一个权值,选择若干不相交的边,得到的总权值最大. 2 解决方案 对于此问题的讲解 ...
- 算法笔记_133:最大连续乘积子数组(Java)
目录 1 问题描述 2 解决方案 2.1 蛮力法 2.2 动态规划法 1 问题描述 给定一个浮点数组,任意取出数组中的若干个连续的数相乘,请找出其中乘积最大的子数组. 2 解决方案 2.1 蛮力法 ...
- 算法笔记_131:出现次数超过一半的数(Java)
目录 1 问题描述 2 解决方案 2.1 每次删除两个不同的数 2.2 记录两个值 1 问题描述 数组中有一个数出现的次数超过了数组长度的一半,请找出这个数. 2 解决方案 2.1 每次删除两个不 ...
- 算法笔记_044:表达式计算求值(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的 ...
- 算法笔记_052:蓝桥杯练习Multithreading(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 现有如下一个算法: repeat ni times yi := y y := yi+1 end repeat 令n[1]为你需要算加法的第 ...
- 算法笔记_013:汉诺塔问题(Java递归法和非递归法)
目录 1 问题描述 2 解决方案 2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus ...
- 算法笔记_198:历届试题 打印十字图(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示: ..$$$$$$$$$$$$$....$...........$..$$ ...
随机推荐
- 51nod1515 明辨是非 并查集 + set
一开始想的时候,好像两个并查集就可以做......然后突然懂了什么.... 相同的并查集没有问题,不同的就不能并查集了,暴力的来个set就行了..... 合并的时候启发式合并即可做到$O(n \log ...
- 2018/3/18 noip模拟赛 20分
T1 dp,特别裸特别简单,我放弃了写了个dfs. T2 树归,特别裸特别简单,我不会写. T3 贪心二分不知道什么玩意儿反正不会写就对了. 我是个智障
- poj 1743 后缀数组 求最长不重叠重复子串
题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题. “主题”是整个音符序列的一个子串,它需要满足如下条件:1 ...
- bzoj 3052 树上莫队 待修改
感谢: http://vfleaking.blog.163.com/blog/static/174807634201311011201627/ http://hzwer.com/5250.html 好 ...
- bzoj 1009 DP 矩阵优化
原来的DP: dp[i][j]表示长度为i的合法串,并且它的长度为j的后缀是给定串的长度为j的前缀. 转移: i==0 dp[0][0] = 1 dp[0][1~m-1] = 0 i>=1 dp ...
- JDK源码(1.7) -- java.util.ListIterator<E>
java.util.ListIterator<E> 源码分析(JDK1.7) ------------------------------------------------------- ...
- sql中字符分割,日期判断,以及函数的应用
前两天公司有一个功能需求,客户给出几天的工作时间和休息,然后顾客的访问时间必须要在工作时间之内和休息时间之外,所以要求做一下判断.本来以为这个没什么,谁知道客户提供的工作时间段和休息时间段不定,给出的 ...
- TortoiseSVN 修改密码
在第一次使用TortoiseSVN从服务器CheckOut的时候,会要求输入用户名和密码,这时输入框下面有个选项是保存认证信息,如果选了这个选项,那么以后就不用每次都输入一遍用户名密码了. 不过,如果 ...
- HDU 4611 Balls Rearrangement(2013多校2 1001题)
Balls Rearrangement Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Othe ...
- ubuntu systemtap-sdt-dev
http://kr.archive.ubuntu.com/ubuntu/pool/universe/s/systemtap/systemtap-sdt-dev_3.0-7_amd64.deb