最短路径(树形DP)

最短路径

给定一个带权无向图。顶点从1到n编号。求从1号点到n号点的最短路径。
 

输入

第一行输入两个整数n(2 \le n \le 10^5), m(0 \le m \le 10^5)n(2n105),m(0m105)。
接下来m行,每行输入三个整数a_i, b_i(1 \le a_i, b_i \le n), w_i(1 \le w_i \le 10^6)ai,bi(1ai,bin),wi(1wi106),表示a_iaib_ibi之间有一条长度为w_iwi的无向边。
 

输出

如果1到n不连通,则输出-1,否则输出最短路径长度。
 

样例

输入

5 4
1 2 2
1 4 1
4 3 3
3 5 1

输出

5
 1 /*************************************************************************
 2     > Author: Henry Chen
 3     > Mail: 390989083@qq.com 
 4  ************************************************************************/
 5 #include<bits/stdc++.h>
 6 using namespace std;
 7 const int N = 10009;
 8 struct edge
 9 {
10     int v,w;
11 }e[2*N];
12 int head[N],nxt[2*N];
13 int tot = 0;
14 int n,m,s;
15 long long dp[N][15];
16 void add_edge(int u,int v,int w)
17 {
18     e[++tot] = (edge){v,w};
19     nxt[tot] = head[u];
20     head[u] = tot;
21 }
22 void dfs(int u,int fa)
23 {
24 
25     for(int i = head[u];i != -1;i = nxt[i])
26     {
27         int v = e[i].v;
28         long long w = 1ll*e[i].w;
29         if(v != fa)
30         {
31             dfs(v,u);
32             for(int j = m;j >= 1;j--)
33             {
34                 dp[u][j] += dp[v][0] + 2 * w;
35                 for(int k = 1;k <= j;k++)
36                 {
37                     dp[u][j] = min(dp[u][j],dp[u][j-k]+dp[v][k]+w * k);
38                 }
39             }
40             dp[u][0] += dp[v][0] + 2 * w;
41         }
42     }
43 }
44 int main()
45 {
46     cin >> n >> s >> m;
47     memset(head,-1,sizeof(head));
48     memset(dp,0,sizeof(dp));
49     tot = 0;
50     for(int i = 1;i < n;i++)
51     {
52         int u,v,w;
53         scanf("%d%d%d",&u,&v,&w);
54         add_edge(u,v,w);
55         add_edge(v,u,w);
56     }
57     dfs(s,-1);
58     printf("%lld\n",dp[s][m]);
59     return 0;
60 }

 

posted @ 2020-08-30 22:36  秘之洋洋  阅读(231)  评论(0编辑  收藏  举报