给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。
往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他点走,直到所有点都走过。
可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。
第一行输入三个正整数n,m,K,表示有n个点m条边,要求的路径需要经过K个点。接下来输入m行,每行三个正整数Ai,Bi,Ci(1<=Ai,Bi<=n,1<=Ci<=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。
输出一行两个整数,以一个空格隔开,第一个整数表示包含K个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<queue>
5 #include<vector>
6 #include<cstring>
7 #define M 100010
8 #define inf 1e9
9 using namespace std;
10 int n,m,num,ans1,ans2,S,rt,k;
11 int head[M],dis[M],d[M],g[M],size[M],maxn[M],f[M][2];
12 bool vis[M];
13 struct point{int to,next,dis;}e[M<<1];
14 struct edge{int to,dis;};
15 struct node{int id,v;};
16 vector<edge>vec[M];
17 priority_queue<node>Q;
18 bool operator < (node a1,node a2) {
19 return a1.v>a2.v;
20 }
21 void add(int from,int to,int dis) {
22 e[++num].next=head[from];
23 e[num].to=to;
24 e[num].dis=dis;
25 head[from]=num;
26 }
27 void Dijkstra(int s) {
28 memset(dis,63,sizeof(dis));
29 dis[s]=0;
30 Q.push((node){s,0});
31 while(!Q.empty()) {
32 int x=Q.top().id;Q.pop();
33 if(vis[x]) continue;
34 for(int i=0;i<vec[x].size();i++) {
35 int to=vec[x][i].to;
36 if(dis[to]>dis[x]+vec[x][i].dis) {
37 dis[to]=dis[x]+vec[x][i].dis;
38 Q.push((node){to,dis[to]});
39 }
40 }
41 }
42 }
43 void build(int x) {
44 vis[x]=true;
45 for(int i=0;i<vec[x].size();i++) {
46 int to=vec[x][i].to;
47 if(vis[to]) continue;
48 if(dis[x]+vec[x][i].dis==dis[to]) {
49 build(to);
50 add(x,to,vec[x][i].dis);
51 add(to,x,vec[x][i].dis);
52 }
53 }
54 }
55 void getroot(int x,int fa) {
56 size[x]=1;maxn[x]=0;
57 for(int i=head[x];i;i=e[i].next) {
58 int to=e[i].to;
59 if(to==fa||vis[to]) continue;
60 getroot(to,x),size[x]+=size[to];
61 maxn[x]=max(maxn[x],size[to]);
62 }
63 maxn[x]=max(maxn[x],S-size[x]);
64 if(maxn[x]<maxn[rt]) rt=x;
65 }
66 void cal(int x,int fa) {
67 if(d[x]>k) return;
68 if(ans1<g[x]+f[k-d[x]+(d[x]!=k)][0]) ans1=g[x]+f[k-d[x]+(d[x]!=k)][0],ans2=f[k-d[x]+(d[x]!=k)][1];
69 else if(ans1==g[x]+f[k-d[x]+(d[x]!=k)][0]) ans2+=f[k-d[x]+(d[x]!=k)][1];
70 for(int i=head[x];i;i=e[i].next) {
71 int to=e[i].to;
72 if(to==fa||vis[to]) continue;
73 d[to]=d[x]+1,g[to]=g[x]+e[i].dis;
74 cal(to,x);
75 }
76 }
77 void insert(int x,int fa) {
78 if(d[x]<=k) {
79 if(f[d[x]][0]<g[x]) f[d[x]][0]=g[x],f[d[x]][1]=1;
80 else if(f[d[x]][0]==g[x]) f[d[x]][1]++;
81 for(int i=head[x];i;i=e[i].next)
82 if(!vis[e[i].to]&&e[i].to!=fa)
83 insert(e[i].to,x);
84 }
85 }
86 void del(int x,int fa) {
87 if(d[x]<=k) {
88 f[d[x]][0]=f[d[x]][1]=-inf;
89 for(int i=head[x];i;i=e[i].next)
90 if(!vis[e[i].to]&&e[i].to!=fa)
91 del(e[i].to,x);
92 }
93 }
94 void solve(int x) {
95 //cout<<x<<endl;
96 vis[x]=true;f[0][0]=0,f[0][1]=1;
97 for(int i=head[x];i;i=e[i].next) {
98 int to=e[i].to;
99 if(vis[to]) continue;
100 d[to]=2,g[to]=e[i].dis,cal(to,x);
101 insert(to,x);
102 }
103 for(int i=head[x];i;i=e[i].next)
104 if(!vis[e[i].to])
105 del(e[i].to,x);
106 for(int i=head[x];i;i=e[i].next) {
107 int to=e[i].to;
108 if(vis[to]) continue;
109 S=size[to],rt=0,getroot(to,0);
110 solve(rt);
111 }
112 }
113 int main() {
114 scanf("%d%d%d",&n,&m,&k);
115 memset(f,128,sizeof(f));
116 for(int i=1;i<=m;i++) {
117 int a,b,c;scanf("%d%d%d",&a,&b,&c);
118 vec[a].push_back((edge){b,c});
119 vec[b].push_back((edge){a,c});
120 }
121 Dijkstra(1),memset(vis,0,sizeof(vis)),build(1);
122 memset(vis,0,sizeof(vis)),maxn[0]=S=n,getroot(1,0);
123 solve(rt);printf("%d %d",ans1,ans2);
124 return 0;
125 }