题意:给你n个城市,每个城市都有一个风景值,再给你m条路,每条路连接两个城市,只能从序号小的到序号大的,
问你从1号到n+1(就是1号)号能经过的风景值得和最大为多少,并且输出路径。
思路:很容易想到可以用求最短路的方法求一个最长路;因为满足只能从小序号的城市到大序号的城市,所以也可以用DP来做,从小的城市开始遍历更新。
(注意每个测试预处理的时候别忘了把n+1也清空)
最短路代码:
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Vector;
public class Main {
static final int maxn = 105;
static final int INF = 0x3f3f3f3f;
static int[] dis = new int[maxn];
static int[] cost = new int[maxn];
static int[] pre = new int[maxn];
static int[] rec = new int[maxn];
static boolean[] book = new boolean[maxn];
static Vector<Integer>[] g = new Vector[maxn];
static void spfa() {
Arrays.fill(pre, -1);
Arrays.fill(dis, 0);
Arrays.fill(book, false);
Queue<Integer> q = new LinkedList<Integer>();
q.clear();
q.add(1);
dis[1] = 0;
while (!q.isEmpty()) {
int u = q.poll();
book[u] = false;
for (int i = 0; i < g[u].size(); i++) {
int v = g[u].get(i);
if (dis[u] + cost[v] >= dis[v]) {
dis[v] = dis[u] + cost[v];
pre[v] = u;
if (!book[v]) {
book[v] = true;
q.add(v);
}
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < maxn; i++)
g[i] = new Vector<Integer>();
int _, n, m, ca = 1;
_ = sc.nextInt();
while (_-- != 0) {
for (int i = 0; i < maxn; i++) {
g[i].clear();
cost[i] = 0;
}
n = sc.nextInt();
for (int i = 1; i <= n; i++)
cost[i] = sc.nextInt();
m = sc.nextInt();
for (int i = 1; i <= m; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
if (u > v) {
int t = u;
u = v;
v = t;
}
g[u].add(v);
}
spfa();
System.out.println("CASE " + (ca++) + "#");
System.out.println("points : " + dis[n + 1]);
System.out.print("circuit : ");
int cnt = 0;
int p = n + 1;
while (p != -1) {
rec[cnt++] = p;
p = pre[p];
}
for (int i = cnt - 1; i > 0; i--)
System.out.print(rec[i] + "->");
System.out.println("1");
if (_ != 0)
System.out.println();
}
}
}
DP代码:
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Vector;
public class Main {
static final int maxn = 105;
static final int INF = 0x3f3f3f3f;
static int[] dp = new int[maxn];
static int[] cost = new int[maxn];
static int[] pre = new int[maxn];
static int[] rec = new int[maxn];
static Vector<Integer>[] g = new Vector[maxn];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < maxn; i++)
g[i] = new Vector<Integer>();
int _, n, m, ca = 1;
_ = sc.nextInt();
while (_-- != 0) {
for (int i = 0; i < maxn; i++) {
g[i].clear();
cost[i] = 0;
}
n = sc.nextInt();
for (int i = 1; i <= n; i++)
cost[i] = sc.nextInt();
m = sc.nextInt();
for (int i = 1; i <= m; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
if (u > v) {
int t = u;
u = v;
v = t;
}
g[u].add(v);
}
Arrays.fill(dp, 0);
Arrays.fill(pre, -1);
for (int i = 1; i <= n; i++) {
int u = i;
for (int j = 0; j < g[i].size(); j++) {
int v = g[i].get(j);
if (dp[u] + cost[v] > dp[v]) {
dp[v] = dp[u] + cost[v];
pre[v] = u;
}
}
}
System.out.println("CASE " + (ca++) + "#");
System.out.println("points : " + dp[n + 1]);
System.out.print("circuit : ");
int cnt = 0;
int p = n + 1;
while (p != -1) {
rec[cnt++] = p;
p = pre[p];
}
for (int i = cnt - 1; i > 0; i--)
System.out.print(rec[i] + "->");
System.out.println("1");
if (_ != 0)
System.out.println();
}
}
}