给定一张包含 N 个点、 N-1 条边的无向连通图,节点从 1 到 N 编号,每条边的长度均为 1 。假设你从 1 号节点出发并打算遍历所有节点,那么总路程至少是多少?
数据范围: 
第一行包含一个整数N。
接下来N-1行,每行包含两个整数X和Y,表示X号节点和Y号节点之间有一条边。
输出总路程的最小值。
4 1 2 1 3 3 4
4
2 1 2
1
#include <bits/stdc++.h>
using namespace std;
int sum = 0;
const int N = 100003;
vector<int> v[N];
void DFS(int x, int pre, int w){
for(int i=0;i<v[x].size();i++){
if(v[x][i]!=pre)
DFS(v[x][i], x, w+1);
}
sum = max(sum, w);
}
int main(){
int n,x,y;
cin>>n;
for(int i=1;i<=n-1;i++){
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
DFS(1, -1, 0);
cout<<2*(n-1)-sum<<endl;
return 0;
} import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
List<List<Integer>> map = new ArrayList<>(n + 1);
for (int i = 0; i <= n; i++) {
map.add(new ArrayList<>());
}
for (int i = 1; i <= n - 1; i++) {
int x = sc.nextInt();
int y = sc.nextInt();
List<Integer> lst = map.get(x);
lst.add(y);
lst = map.get(y);
lst.add(x);
}
boolean[] vis = new boolean[n + 1];
class Element {
private int point;
private int deep;
private Element(int point, int deep) {
this.point = point;
this.deep = deep;
}
}
Queue<Element> queue = new LinkedList<>();
queue.add(new Element(1, 0));
vis[1] = true;
int max = 0;
while (!queue.isEmpty()) {
Element p = queue.poll();
if(p.deep > max) {
max = p.deep;
}
List<Integer> lst = map.get(p.point);
if(lst.isEmpty()) {
continue;
}
for (int t : lst) {
if(!vis[t]) {
vis[t] = true;
queue.add(new Element(t, p.deep + 1));
}
}
}
System.out.println(2 * (n - 1) - max);
}
} #include <iostream>
#include <vector>
using namespace std;
int maxDepth(vector<vector<int>>& g, vector<int>& vis, int curr) {
vis[curr] = 1;
int max_depth = 0;
for (const int nxt : g[curr]) {
if (vis[nxt]) continue;
int depth = maxDepth(g, vis, nxt);
max_depth = max(max_depth, depth);
}
return 1 + max_depth;
}
int main(const int argc, const char* argv[]) {
int n;
cin >> n;
vector<vector<int>> g(n + 1);
vector<int> vis(n + 1, 0);
int u, v;
for (int i = 0; i < n - 1; ++i) {
cin >> u >> v;
g[u].emplace_back(v);
g[v].emplace_back(u);
}
cout << (n << 1) - maxDepth(g, vis, 1) - 1;
return 0;
} #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#define OK 1
#define ERROR -1
#define MEMORY_OVERFLOW -2
#define NOT !
#define DEFAULT_CAPACITY 1E5
#define InitQueue(Q) __InitQueue(Q, DEFAULT_CAPACITY)
typedef int Status;
// ==================== 循环队列存储结构表示与实现 ====================
typedef int QElemType;
typedef struct CircularQueue {
QElemType* base;
int front;
int rear;
size_t capacity;
} SqQueue;
Status __InitQueue(SqQueue* Q, int initialCapacity) {
if (initialCapacity < 1) {
fprintf(stderr,
"__InitQueue ERROR: The intitialCapacity %d Must be > 0!",
initialCapacity);
return ERROR;
}
if (!((*Q).base = (QElemType*) malloc((initialCapacity + 1) * sizeof(QElemType)))) {
fprintf(stderr, "__InitQueue Memory Overflow: %s\n", strerror(errno));
exit(MEMORY_OVERFLOW);
}
(*Q).front = (*Q).rear = 0;
(*Q).capacity = initialCapacity + 1;
return 0;
}
bool QueueEmpty(SqQueue* Q) {
return (*Q).front == (*Q).rear;
}
bool QueueFull(SqQueue* Q) {
return ((*Q).rear + 1) % (*Q).capacity == (*Q).front;
}
size_t QueueLength(SqQueue* Q) {
return ((*Q).rear - (*Q).front + (*Q).capacity) % (*Q).capacity;
}
void __large_capacity(SqQueue* Q) {
}
Status EnQueue(SqQueue* Q, QElemType e) {
if (QueueFull(Q))
__large_capacity(Q);
(*Q).rear = ((*Q).rear + 1) % (*Q).capacity;
*((*Q).base + (*Q).rear) = e;
return OK;
}
Status DeQueue(SqQueue* Q, QElemType* e) {
if (QueueEmpty(Q)) {
fputs("DeQueue ERROR: The queue is empty!", stderr);
return ERROR;
}
(*Q).front = ((*Q).front + 1) % (*Q).capacity;
*e = *((*Q).base + (*Q).front);
return OK;
}
Status DestroyQueue(SqQueue* Q) {
free((*Q).base);
return OK;
}
// ==================== 循环队列存储结构表示与实现 ====================
// ==================== The begin of function prototype ====================
void addEdge(int* head, int* to, int* next, const int u, const int v, int* edge_count);
void printGraph(int* head, int* to, int* next, const int n);
int breath_first_search_algorithm(const int n, int* head, int* to, int* next);
// ==================== The begin of function prototype ====================
int main(const int argc, char** argv) {
int n;
fscanf(stdin, "%d", &n);
// 图的邻接链表(adjacency list)表示法
int m = n - 1; // m为边的数量
int head[n + 1], to[m << 1 + 1], next[m << 1 + 1];
memset(head, 0x0000, sizeof head);
int u, v, edge_count = 0;
while (m--) { // 构建无向图
fscanf(stdin, "%d %d", &u, &v);
addEdge(head, to, next, u, v, &edge_count);
addEdge(head, to, next, v, u, &edge_count);
}
// printGraph(head, to, next, n);
int longest = breath_first_search_algorithm(n, head, to, next);
fprintf(stdout, "%d\n", (n - 1) * 2 - longest);
return 0;
}
void addEdge(int* head, int* to, int* next, const int u, const int v, int* edge_count) {
++(*edge_count);
*(next + *edge_count) = *(head + u);
*(to + *edge_count) = v;
*(head + u) = *edge_count;
}
int breath_first_search_algorithm(const int n, int* head, int* to, int* next) {
SqQueue Q;
InitQueue(&Q);
EnQueue(&Q, 1);
int seen[n + 1];
memset(seen, 0x0000, sizeof seen);
seen[1] = 1;
int i, curr, steps = 0;
while (NOT QueueEmpty(&Q)) {
size_t s = QueueLength(&Q);
while (s--) {
DeQueue(&Q, &curr);
for (i = head[curr]; i; i = next[i]) {
int nei = *(to + i);
if (*(seen + nei)) continue;
EnQueue(&Q, nei);
*(seen + nei) = 1;
}
}
++steps;
}
return DestroyQueue(&Q), steps - 1;
}
void printGraph(int* head, int* to, int* next, const int n) {
int i, u;
for (u = 1; u <= n; ++u) {
fprintf(stdout, "vertex %d [ ", u);
for (i = head[u]; i; i = next[i])
fprintf(stdout, "%d ", to[i]);
fputs("]\n", stdout);
}
}
/*借用一下别人的代码,讲下思路: 其实就是每条边都会走两遍,一共有n-1条边,所以2*(n-1), 最后一条路径只需要走一次,所以减去最后一条路径的长度。本质来说,就是求一个图的最长路径*/#include <bits/stdc++.h>usingnamespacestd;constintN = 1e5+10;vector<int> vec[N];intans;voiddfs(intx, intold, intw) {for(inti=0;i<vec[x].size();i++){if(vec[x][i]==old){continue;}dfs(vec[x][i],x,w+1);}ans = max(ans, w);}intmain() {intn;scanf("%d", &n);for(inti = 1; i < n; ++ i) {intx, y;scanf("%d%d", &x, &y);vec[x].push_back(y);vec[y].push_back(x);}ans = 0;dfs(1, -1, 0);printf("%d\n", (n-1)*2-ans);return0;}
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
Map<Integer,List<Integer>> map = new HashMap<>();
for(int i=0;i<n-1;i++){
int num1 = in.nextInt();
int num2 = in.nextInt();
if(map.get(num1)==null)
map.put(num1,new ArrayList<Integer>());
if(map.get(num2)==null)
map.put(num2,new ArrayList<Integer>());
map.get(num1).add(num2);
map.get(num2).add(num1);
}
//bfs
boolean[] flags = new boolean[n+1];
Queue<Integer> queue = new LinkedList<>();
queue.offer(1);
flags[1]=true;
int res=-1;
while(!queue.isEmpty()){
int l = queue.size();
for(int i=0;i<l;i++){
int nu = queue.poll();
List<Integer> tlist = map.get(nu);
if(tlist==null)
continue;
for(Integer num:tlist){
if(flags[num]==true)
continue;
flags[num]=true;
queue.offer(num);
}
}
res++;
}
System.out.println((n-1)*2-res);
}
} 由题意得:n个点,n-1条边组成得图是无环图,所以要遍历所有点,最少得走法是所有边走俩两边再减去图中得最长路径,所以本题可以理解为,用bfs求图得最长路径
from collections import defaultdict
d = defaultdict(list)
n = int(input())
for i in range(n-1):
a,b = map(int, input().split())
d[a].append(b)
d[b].append(a)
visited = defaultdict(bool)
visited[1] = True
res = 0
stack = [1]
while len(stack) > 0:
tmp = []
while len(stack) > 0:
t = stack.pop()
for e in d[t]:
if not visited[e]:
visited[e] = True
tmp.append(e)
stack = tmp
res += 1
print(2 * (n-1) - res + 1)
#include<iostream>
(720)#include<vector>
#include<queue>
(789)#include<algorithm>
#define N 100001
using namespace std;
int n,deg=0;
bool visit[N]={false};
vector<int> map[N];
int main()
{
int x,y;
cin>>n;
for(int i=0;i<n-1;i++)
{
cin>>x>>y;
map[x].push_back(y);
map[y].push_back(x);
}
queue<int> Q;
Q.push(1);
int p,end=1,nend,adj;
while(!Q.empty())
{
p=Q.front();
visit[p]=true;
//cout<<p<<' '<<data[p].degree<<endl;
Q.pop();
for(int i=0;i<map[p].size();i++)
{
adj=map[p][i];
if(!visit[adj])
{
Q.push(adj);
nend=adj;
}
}
if(p==end)
{
end=nend;
deg++;
}
}
deg--;
cout<<2*(n-1)-deg;
return 0;
}
n = int(input())
edge = [[] for _ in range(n)]
for _ in range(n-1):
x, y = map(int, input().split(" "))
edge[x-1].append(y-1)
edge[y-1].append(x-1)
visited = [0 for _ in range(n)]
visited[0] = 1
# 从当前根节点开始到返回当前根节点的路程为2*(n-1),n为节点个数,即根节点的子节点个数的2倍
# 求树的深度
queue = [0]
depth = 0
while len(queue)>0:
depth += 1
size = len(queue)
for _ in range(size):
now = queue.pop(0)
for j in edge[now]:
if visited[j]==0:
visited[j]=1
queue.append(j)
print((n-1)*2-depth+1)
过了93.33%后超时了,还能怎么优化啊
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
static int max = 0;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
int n = in.nextInt();
HashMap<Integer, List<Integer>> map = new HashMap<>();
for (int i=0; i<n-1; i++) {
int key = in.nextInt();
int val = in.nextInt();
if (map.containsKey(key)) {
List<Integer> list = map.get(key);
list.add(val);
map.put(key, list);
} else {
List<Integer> list = new ArrayList<>();
list.add(val);
map.put(key, list);
}
}
dfs(map, 1, 0);
System.out.print(2*(n-1) - max);
}
private static void dfs(HashMap<Integer, List<Integer>> map, int key, int num) {
if (!map.containsKey(key)) {
max = Math.max(max, num);
return;
}
num++;
for (Integer i : map.get(key)) {
dfs(map, i, num);
}
}
} #include <iostream>
#include <cstring>
#include <queue>
using namespace std;
//使用深度优先搜索
const int MAXN=100002;
vector<int> matrix[MAXN];
//int num[MAXN];
int longer[MAXN];
bool flag[MAXN];
int dfs(int a) //使用深度优先遍历a这个点下面的最长路径,
{
for(int i=0;i<matrix[a].size();i++)
{
int x=matrix[a][i];
if(flag[x])
{
flag[x]=false;
int l=dfs(x);
flag[x]=true;
if(l+1> longer[a])
{
longer[a]=l+1;
}
}
}
return longer[a];
}
int main()
{
int n;
while(cin>>n)
{
//存储数据
for(int i=0;i<n-1;i++)
{
int from, to;
cin>>from>>to;
matrix[from].push_back(to);
matrix[to].push_back(from);
}
//初始化longer
for(int i=0;i<=n;i++)
{ longer[i]=0;
flag[i]=true;
}
//深度优先搜索
flag[1]=false;
dfs(1);
cout<<2*(n-1)-longer[1]<<endl;
}
return 0;
} public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
List<LinkedList<Integer>> list = new LinkedList();
for(int i = 0; i < n; i++){
list.add(new LinkedList<Integer>());
}
int[] visited = new int[n];
for(int i = 0; i < n-1; i++){
int f = sc.nextInt()-1;
int e = sc.nextInt()-1;
list.get(f).add(e);
list.get(e).add(f);
}
int max_path = -1;
//BFS
Deque<Integer> queue = new LinkedList();
queue.offerLast(0);
visited[0] = 1;
while(queue.size() > 0){
int nums = queue.size();
while(nums>0){
int node = queue.pollFirst();
for(int i = 0; i < list.get(node).size(); i++){
int j = list.get(node).get(i);
if(visited[j]==0){
visited[j] = 1;
queue.offerLast(j);
}
}
nums--;
}
max_path++;
}
System.out.println(2*(n-1)-max_path);
} n = int(input())
path = {i: [] for i in range(n)}
for i in range(n-1):
s, e = [int(i) - 1 for i in input().split()]
path[s].append(e)
path[e].append(s)
visited = [False] * n
stack = [0]
visited[0] = True
depth = 0
while stack:
t = []
while stack:
node = stack.pop()
for child in path[node]:
if visited[child]:
continue
else:
visited[child] = True
t.append(child)
stack = t
if stack:
depth += 1
print(2*(n-1) - depth) #include <iostream>
#include <vector>
#include <string>
#include <string.h>
#include <sstream>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <cmath>
#include <numeric>
using namespace std;
int main(){
int N;
cin>>N;
vector<pair<int, int>> P(N-1);
vector<vector<int>> matrix(N+1);
for (int i = 0; i < N-1; ++i) {
cin>>P[i].first>>P[i].second;
}
for (int i = 0; i < N-1; ++i) {
matrix[P[i].first].push_back(P[i].second);
matrix[P[i].second].push_back(P[i].first);
}
vector<bool> isVisted(N, false);
queue<int> Q;
isVisted[1] = true;
Q.push(1);
int num = 1;
int level = 0;
int count = 0;
while(!Q.empty()){
int val = Q.front();
Q.pop();
for (int i = 0; i < matrix[val].size(); ++i) {
if(!isVisted[matrix[val][i]]) {
Q.push(matrix[val][i]);
isVisted[matrix[val][i]] = true;
++count;
}
}
--num;
if(num == 0){
++level;
num = count;
count = 0;
}
}
cout<<2*(N-1)-level+1<<endl;
return 0;
}
非递归的BFS
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;
/**
* @Author: coderjjp
* @Date: 2020-05-10 20:05
* @Description: 图的遍历--本题本质是求树的高度或者理解为从1出发的最长路径
* @version: 1.0
*/
public class Main {
static int len = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
HashMap<Integer, ArrayList<Integer>> graph = new HashMap<>();
for (int i = 1; i <= N; i++)
graph.put(i, new ArrayList<>());
String[] s;
int num[] = new int[2];
for (int i = 0; i < N - 1; i++){
s = br.readLine().split(" ");
num[0] = Integer.parseInt(s[0]);
num[1] = Integer.parseInt(s[1]);
graph.get(num[0]).add(num[1]);
graph.get(num[1]).add(num[0]);
}
boolean flag[] = new boolean[N+1];
Stack<Integer> stack = new Stack<>();
Stack<Integer> temp;
stack.push(1);
flag[1] = true;
while (!stack.isEmpty()){
temp = new Stack<>();
while (!stack.isEmpty()){
Integer pop = stack.pop();
for (int son: graph.get(pop))
if (!flag[son]){
temp.push(son);
flag[son]=true;
}
}
if (!temp.isEmpty())
len++;
stack = temp;
}
System.out.println(2*(N-1) - len);
}
} #处理stack有两种方式,一是记录原来长度,切片 (3755)#二是直接把新元素添加给临时数组,直接赋值或者深拷贝 N = int(input()) edge = [[] for i in range(N)] stack = [] for i in range(N-1): x, y = map(int,input().split()) edge[x-1].append(y - 1) edge[y-1].append(x - 1) visit = [False for i in range(N)] visit[0] = True stack.append(0) depth = 1 while len(stack) > 0: temp = [] flag = False while len(stack) > 0: i = stack.pop() for j in edge[i]: if visit[j]: continue else: temp.append(j) visit[j] = True flag = True if flag: depth += 1 stack = temp[:] print(2 * N - 1 - depth)
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
boolean[] visit = new boolean[n+1];
for(int i=0;i<n+1;i++)
visit[i] = false;
List<List<Integer>> map = new ArrayList<> ();
for(int i=0;i<=n;i++) {
List<Integer> lst = new ArrayList<Integer>();
lst.add(i);
map.add(lst);
}
for(int i=1;i<n;i++) {
int x = sc.nextInt();
int y = sc.nextInt();
List<Integer> lst = map.get(x);
lst.add(y);
lst = map.get(y);
lst.add(x);
}//graph
class Element{
int point;
int deep;
Element(int point, int deep){
this.point = point;
this.deep = deep;
}
}
Queue<Element> queue = new LinkedList<>();
Element e = new Element(1,0);
visit[1] = true;
int max = 0;
queue.offer(e);
while(!queue.isEmpty()) {
Element temp = queue.poll();
max=Math.max(max, temp.deep);
List<Integer> lst = map.get(temp.point);
for(int i=1;i<lst.size();i++) {
if(!visit[lst.get(i)]) {
visit[lst.get(i)]=true;
queue.offer(new Element(lst.get(i),temp.deep+1));
}
}
}
int distance = 2*((n-1)-max)+max;
System.out.println(distance);
}
}
package main
import (
"fmt"
"math"
)
var (
sum = 0
v = make(map[int][]int, N)
visted = make(map[int]int, N)
N = 1000
)
func dfs(x int, w int) {
for i := 0; i < len(v[x]); i++ {
if visted[v[x][i]] == 0 {
visted[v[x][i]] = 1
dfs(v[x][i], w+1)
}
}
sum = int(math.Max(float64(sum), float64(w)))
}
func main() {
var a, b int
fmt.Scanf("%d", &N)
for i := 1; i <= N; i++ {
visted[i] = 0
}
for i := 1; i <= N-1; i++ {
fmt.Scanf("%d %d", &a, &b)
v[a] = append(v[a], b)
v[b] = append(v[b], a)
}
visted[1]=1
dfs(1, 0)
fmt.Println(2*(N-1) - sum)
}