算法笔记_149:图论之桥的应用(Java)
2017-04-27 12:39
387 查看
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 解决方案
首先看看关于图论的割点和桥的相关概念定义:[b]引用文末参考资料1:[/b]
1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点。
具体代码如下:
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.add(new edge(b, a, c)); } test.getResult(); } }
[b][b]运行结果:[/b]
4 4 4 1 1 4 2 2 1 2 1 1 3 2 2 4 1 1 3 2
[b]参考资料:[/b]
1.图论-桥/割点/双连通分量/缩点/LCA
2. uva 1310 - One-way traffic(连通分量)
3.【图论】求无向连通图的割点
相关文章推荐
- 算法笔记_150:图论之双连通及桥的应用(Java)
- 算法笔记_145:拓扑排序的应用(Java)
- 算法笔记_146:TarJan算法的应用(Java)
- java笔记--超级类Object多线程的应用+哲学家进餐算法内部类与多线程结合
- 算法笔记_147:有向图欧拉回路判断应用(Java)
- JAVA高级应用学习笔记----流
- Memcached学习笔记 - 在JAVA中的应用
- Java Socket套接字应用实例-java学习笔记(1)
- Servlet学习笔记(一)javaWeb应用基本
- JAVA高级应用学习笔记----流
- 黑马程序员________Java中IO技术字节流字符流的应用及File类学习笔记
- Flex企业应用开发实践学习笔记(八)——Flex on Java企业应用架构
- Java 线程同步问题 生产者-消费者 算法实现 -Java学习笔记(29)
- 《Spring 3.x 企业应用开发实战》学习笔记 第三章 IoC容器概述 3.2 相关Java基础知识 类装载器 反射机制
- 分布式java应用学习笔记一
- Java数组扩容算法及Java对它的应用
- java笔记:SpringSecurity应用(二)
- IDEA算法及应用(java)
- 应用JAVA进行密码加密的一种算法
- Java学习笔记---8.面向对象编程03-String类的重点应用