洛谷 P1967 货车运输 java实现
作者:互联网
题目链接:
https://www.luogu.com.cn/problem/P1967
是一道最小生成树+LCA的模板组合题目.
代码比较长....
计算最多能运送多少重量的货物,首先会想到计算最大生成树.这样就能够保证联通所有路的情况下,道路载重最大.
因为最终计算的是某两点之间的最大载重量,所以我们需要计算两点之间的路径上最小的载重是多少.
在倍增法LCA中,我们通过动态规划可以计算出每个节点的跳跃路径,我们也可以使用同样的方式记录在跳跃过程中,道路的最小载重.
for (int j = 1; j <= maxLevel; j++) {
for (int i = 1; i <= n; i++) {
parentInfo[i][j] = parentInfo[parentInfo[i][j - 1]][j - 1];
parentMinWeightInfo[i][j] = Math.min(parentMinWeightInfo[i][j-1],parentMinWeightInfo[parentInfo[i][j - 1]][j - 1]);
}
}
最终,在进行询问的时候,可以进行比较,得出最终结果.
因为给出的点之间可能并不联通,是一个森林,所以在询问之前,需要进行联通判断.不在一个并查集中,就输出-1.
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int[] p, level;
static PriorityQueue<int[]> pq;
static LinkedList<int[]>[] adj;
static boolean[] isVisit;
static int[][] parentInfo,parentMinWeightInfo;
static int maxLevel,n,m;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
p = new int[n + 1];
pq = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o2[2] - o1[2];
}
});
for (int i = 1; i <= n; i++) {
p[i] = i;
}
int from, to, weight;
for (int i = 1; i <= m; i++) {
st = new StringTokenizer(br.readLine());
from = Integer.parseInt(st.nextToken());
to = Integer.parseInt(st.nextToken());
weight = Integer.parseInt(st.nextToken());
pq.add(new int[]{from, to, weight});
}
adj = new LinkedList[n + 1];
for (int i = 0; i < adj.length; i++) {
adj[i] = new LinkedList<int[]>();
}
int[] edge;
while (!pq.isEmpty()) {
edge = pq.poll();
from = edge[0];
to = edge[1];
weight = edge[2];
if (!connect(from, to)) {
union(from, to);
adj[from].add(new int[]{to, weight});
adj[to].add(new int[]{from, weight});
}
}
isVisit = new boolean[n + 1];
level = new int[n + 1];
for (int i = 1; i <= n; i++) {
if (!isVisit[i]) {
dfs(i,0);
}
}
maxLevel = 0;
for (int i = 1; i <= n; i++) {
maxLevel = Math.max(maxLevel, level[i]);
}
int temp = 0;
while ((1 << temp) < maxLevel) {
temp++;
}
maxLevel = temp;
parentInfo = new int[n + 1][maxLevel + 1];
parentMinWeightInfo = new int[n + 1][maxLevel + 1];
isVisit = new boolean[n + 1];
for (int i = 1; i <= n; i++) {
if (!isVisit[i]) {
parentMinWeightInfo[i][0] = Integer.MAX_VALUE;
dfs2(i);
}
}
for (int j = 1; j <= maxLevel; j++) {
for (int i = 1; i <= n; i++) {
parentInfo[i][j] = parentInfo[parentInfo[i][j - 1]][j - 1];
parentMinWeightInfo[i][j] = Math.min(parentMinWeightInfo[i][j-1],parentMinWeightInfo[parentInfo[i][j - 1]][j - 1]);
}
}
st = new StringTokenizer(br.readLine());
StringBuilder bu = new StringBuilder();
int q = Integer.parseInt(st.nextToken());
int a, b;
for (int i = 0; i < q; i++) {
st = new StringTokenizer(br.readLine());
a = Integer.parseInt(st.nextToken());
b = Integer.parseInt(st.nextToken());
if(!connect(a,b)){
bu.append(-1) ;
if(i != q-1){
bu.append("\n");
}
continue;
}
int ans = LCA(a,b);
bu.append(ans) ;
if(i != q-1){
bu.append("\n");
}
}
System.out.println(bu.toString());
}
private static void dfs(int from,int deep) {
isVisit[from] = true;
level[from] = ++deep;
for (int[] next : adj[from]) {
if (!isVisit[next[0]]) {
dfs(next[0],deep);
}
}
}
private static void dfs2(int from){
isVisit[from] = true;
for (int[] next : adj[from]) {
if (!isVisit[next[0]]) {
parentMinWeightInfo[next[0]][0] = next[1];
parentInfo[next[0]][0] = from;
dfs2(next[0]);
}
}
}
private static int LCA(int a, int b){
if(level[a]<level[b]){
int temp =a;
a = b;
b = temp;
}
int ans = Integer.MAX_VALUE;
for(int i = maxLevel;i>=0;i--){
if(level[parentInfo[a][i]]>=level[b]){
ans = Math.min(ans, parentMinWeightInfo[a][i]);
a = parentInfo[a][i];
}
}
if(a == b){
return ans;
}
for(int i = maxLevel;i>=0;i--){
if(parentInfo[a][i]!=parentInfo[b][i]){
ans = Math.min(ans,Math.min(parentMinWeightInfo[a][i],parentMinWeightInfo[b][i]));
a = parentInfo[a][i];
b = parentInfo[b][i];
}
}
ans = Math.min(ans,Math.min(parentMinWeightInfo[a][0],parentMinWeightInfo[b][0]));
return ans;
}
private static int find(int a) {
if (p[a] == a) {
return p[a];
}
return p[a] = find(p[a]);
}
private static void union(int a, int b) {
int A = find(a);
int B = find(b);
p[A] = B;
}
private static boolean connect(int a, int b) {
return find(a) == find(b);
}
}
标签:parentMinWeightInfo,洛谷,int,货车运输,parentInfo,static,ans,new,P1967 来源: https://www.cnblogs.com/reclusiveone/p/14722898.html