Codeforces - 20C & 115A & 840A & 782C
阿新 • • 發佈:2019-01-07
Codeforces - 20C & 115A & 840A & 782C
- Codeforces - 20C - Dijkstra?
- Codeforces - 115A - Party
- Codeforces - 840A - Leha and Function
- Codeforces - 782C - Andryusha and Colored Balloons
Codeforces - 20C - Dijkstra?
題目連結
題目大意
給你一個有權圖,求從頂點1
到頂點n
的最短路徑。
解析
用一個pre
陣列儲存是由哪個節點更新過來的就可以得到最短路徑。
import java.io.BufferedInputStream;
import java.util.*;
public class Main {
static class Graph{
public int n;
public int m;
public boolean[] vis;
public ArrayList<Edge>g[];
public Graph(int n) {
this .n = n;
vis = new boolean[n];
g = new ArrayList[n];
for(int i = 0; i < n; i++){
vis[i] = false;
g[i] = new ArrayList<>();
}
}
}
static class Edge implements Comparable<Edge>{
public int to;
public int w;
public Edge(int to, int w) {
this.to = to;
this.w = w;
}
@Override
public int compareTo(Edge o) {
return w - o.w;
}
}
static int[] dijkstra(Graph G, int s, int[] pre){
PriorityQueue<Edge>pq = new PriorityQueue<>();
int[] dis = new int[G.n];
for(int i = 0; i < G.n; i++)
dis[i] = Integer.MAX_VALUE; //初始標記(不是-1(因為是求最小的))
pq.add(new Edge(s, 0));
while(!pq.isEmpty()){
Edge curEdge = pq.poll();
int to = curEdge.to;
if(G.vis[to])
continue;
G.vis[to] = true;
for(int i = 0; i < G.g[to].size(); i++){
int nxtNode = G.g[to].get(i).to;
int nxtW = G.g[to].get(i).w;
if(!G.vis[nxtNode] && dis[nxtNode] > dis[to] + nxtW){
dis[nxtNode] = dis[to] + nxtW;
pre[nxtNode] = to; // only add this code
pq.add(new Edge(nxtNode, dis[nxtNode]));
}
}
}
return dis;
}
public static void main(String[] args){
Scanner cin = new Scanner(new BufferedInputStream(System.in));
int n = cin.nextInt();
int m = cin.nextInt();
Graph G = new Graph(n);
for(int i = 0; i < m; i++){
int from = cin.nextInt();
int to = cin.nextInt();
int w = cin.nextInt();
G.g[from-1].add(new Edge(to-1, w));
G.g[to-1].add(new Edge(from-1, w));
}
int[] pre = new int[n];
Arrays.fill(pre, -1);
int[] dis = dijkstra(G, 0, pre);
if(dis[n-1] == Integer.MAX_VALUE){
System.out.println("-1");
return;
}
Stack<Integer>stack = new Stack<>();
int p = n-1;
while(p != -1){
stack.push(p);
p = pre[p];
}
System.out.print(stack.pop()+1);
while(!stack.isEmpty())
System.out.print(" " + (stack.pop()+1));
System.out.println();
}
}
Codeforces - 115A - Party
題目連結
題目大意
給你n
,代表有n
個與員工,然後給你每個員工的直接上司是誰(所有人從1~n
編號),要你將這n
個人分成最少的組,要求: ①每個員工必須屬於某一個組;②一組內的任何兩個人直接不能是上下級關係(包括直接上下級和間接上下級);
解析
題目樣例:
思路很簡單:
- 我們只需要求所有員工到他祖先的路徑長度中最長的那條的長度。因為沒一層都可以屬於一個組,即使有多個連通分量。
- 可以使用和並查集類似的結構,儲存每個節點的父親節點。然後迭代查詢即可。
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
static class UnionSet{
public int[] parent;
public UnionSet(int n) {
parent = new int[n+1];
}
public int findRoot(int v){
int len = 0;
while(parent[v] != v){
v = parent[v];
len++;
}
return len;
}
}
public static void main(String[] args){
Scanner cin = new Scanner(new BufferedInputStream(System.in));
int n = cin.nextInt();
UnionSet uset = new UnionSet(n);
for(int i = 1; i <= n; i++){
int num = cin.nextInt();
if(num == -1)
uset.parent[i] = i;
else
uset.parent[i] = num;
}
int res = -1;
for(int i = 1; i <= n; i++)
res = Math.max(res, uset.findRoot(i)); //最大的那個
System.out.println(res+1);
}
}
Codeforces - 840A - Leha and Function
題目連結
題目大意
給你一個函式F(n, k)
,意思是從1 ~ n
裡選出 k
個數,每次的貢獻是選出的 k
個數中最小的那個數。輸入n
,陣列a、b
要你將a
陣列重新排列,使得F(ai, bi)
的和最大。
解析
貪心,a
陣列更大的要去匹配 b
陣列更小的,這樣才會更大。
將a
陣列升序排列,b
陣列降序排列並記錄之前的索引,最後遍歷將a
陣列中元素放到正確的位置。
import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static class Pair{
public int num;
public int id;
public Pair(int num, int id) {
this.num = num;
this.id = id;
}
}
public static void main(String[] args){
Scanner cin = new Scanner(new BufferedInputStream(System.in));
int n = cin.nextInt();
int[] arr = new int[n];
for(int i = 0; i < n; i++)
arr[i] = cin.nextInt();
Arrays.sort(arr); // 升序排列
Pair[] pairs = new Pair[n];
for(int i = 0; i < n; i++) {
int num = cin.nextInt();
pairs[i] = new Pair(num, i);
}
Arrays.sort(pairs, (o1, o2) -> o2.num - o1.num); // 按照值降序排列
int[] res = new int[n];
for(int i = 0; i < n; i++)
res[pairs[i].id] = arr[i];
for(int i = 0; i < n; i++)
System.out.print(res[i] + " ");
System.out.println();
}
}
Codeforces - 782C - Andryusha and Colored Balloons
題目連結
題目大意
就是給你一顆生成樹(n
個頂點,n-1
條邊),然後輸入n-1
條邊,要你用1 ~ n
之間儘可能少的顏色,來將n
個頂點染色,有一個條件: 相鄰距離為2
的點都是不同的顏色。
輸出總共需要多少種顏色,並且輸出每個頂點的顏色。
解析
寫了挺久(菜),還是沒有維護好count
這個變數,最後還是看了下些解答。
count
變數要在當前節點cur
的所有孩子的迴圈遍歷中count++
,因為遍歷一個之後,就找到了一種,所以遍歷一次就++
,所以一開始dfs
將count = 0
,至於最大值,只需要計算某個節點的最大值即可。
import java.io.BufferedInputStream;
import java.util.*;
public class Main {
static ArrayList<Integer>G[];
static int[] colors;
static int res; // the number of colors
static void dfs(int cur, int pre){
int count = 0;
for(int i = 0; i < G[cur].size(); i++){
int to = G[cur].get(i);
if(pre == to || colors[to] != -1) // 訪問過或者已經計算過
continue;
count++; // it must
while(count == colors[cur] || count == colors[pre])
count++;
colors[to] = count;
dfs(to, cur);
}
res = Math.max(res, count);
}
public static void main(String[] args){
Scanner cin = new Scanner(new BufferedInputStream(System.in));
int n = cin.nextInt();
G = new ArrayList[n+1];
for(int i = 1; i <= n; i++)
G[i] = new ArrayList<>();
colors = new int[n+1];
Arrays.fill(colors, -1);
for(int i = 0; i < n-1; i++){
int from = cin.nextInt();
int to = cin.nextInt();
G[from].add(to);
G[to].add(from);
}
colors[1] = 1;
res = 0;
dfs(1, 0);
System.out.println(res);
for(int i = 1; i < n; i++)
System.out.print(colors[i] + " ");
System.out.println(colors[n]);
}
}