[BZOJ4016]最短路径树问题

Description

给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。
往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他点走,直到所有点都走过。
可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。

Input

第一行输入三个正整数n,m,K,表示有n个点m条边,要求的路径需要经过K个点。接下来输入m行,每行三个正整数Ai,Bi,Ci(1<=Ai,Bi<=n,1<=Ci<=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。
 
 

Output

输出一行两个整数,以一个空格隔开,第一个整数表示包含K个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。
 

Sample Input

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

Sample Output

3 4

设$f[i][0/1]$表示到当前分治重心的路径中点数为$i$的路径最大长度和方案数

然后注意细节就可以$A$掉它了

代码:

  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 }

 

posted @ 2018-11-27 21:00  Slr  阅读(450)  评论(0编辑  收藏  举报