首先是最短路径树,将一个点相连的所有边装入Vector中,排序后倒序加边(因为链表的写法是从最后加入的边向前便利),求出最短路径图后DFS得到最短路径树,然后和普通的点分治一样辣!
要善于利用时间戳(虽然并没有什么卵用)。
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define maxn 60005
#define oo 999999999
struct edge
{
int to,d,next;bool ban;
}e[maxn*5],e2[maxn*5];
struct _pa{int y,d;};
vector<_pa>To[maxn];
bool operator < (_pa x,_pa y)
{
return x.y<y.y;
}
void _read(int &x)
{
bool flag=false;
x=0; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')flag=true; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
if(flag)x=-x;
return ;
}
int edge_ct,n,m,k,edge_ct2,head2[maxn],head[maxn],d[maxn];
bool v[maxn];
void add2(int x,int y,int z)
{
e2[++edge_ct2]=(edge){y,z,head2[x],false};head2[x]=edge_ct2;
return ;
}
void add(int x,int y,int z)
{
e[++edge_ct]=(edge){y,z,head[x],false};head[x]=edge_ct;
e[++edge_ct]=(edge){x,z,head[y],false};head[y]=edge_ct;
return ;
}
struct data
{
int x,y;
};
struct cmp
{
bool operator () (data x,data y)
{
return x.y>y.y;
}
};
priority_queue<data ,vector<data>,cmp>pq;
void Dijkstra()
{
d[1]=0;
for(int i=2;i<=n;i++)d[i]=oo;
for(int i=1;i<=n;i++)v[i]=false;
pq.push((data){1,0});
data t;
int i,id,j;
while(!pq.empty())
{
t=pq.top(); pq.pop();if(v[t.x])continue;
i=t.x; v[i]=true;
for(int id=head2[i];id;id=e2[id].next)
{
j=e2[id].to;
if(d[j]<=d[i]+e2[id].d)continue;
d[j]=d[i]+e2[id].d;
pq.push((data){j,d[j]});
}
}
return ;
}
void DFS_1(int now)
{
v[now]=true;
int j;
for(int id=head2[now];id;id=e2[id].next)
{
j=e2[id].to;
if((v[j]) || d[j]!=d[now]+e2[id].d)continue;
add(now,j,e2[id].d);
// printf("%d %d\n",now,j);
DFS_1(j);
}
return ;
}
void Init()
{
_read(n);_read(m);_read(k);k--;
int x,y,z;
edge_ct2=edge_ct=0;
for(int i=1;i<=m;i++)
{
_read(x); _read(y); _read(z);
To[x].push_back((_pa){y,z});
To[y].push_back((_pa){x,z});
}
for(int i=1;i<=n;i++)
{
// printf("%d:\n",i);
sort(To[i].begin(),To[i].end());
for(int j=To[i].size()-1;j>=0;j--)
{
add2(i,To[i][j].y,To[i][j].d);
// printf("%d %d\n",To[i][j].y,To[i][j].d);
}
}
Dijkstra();
for(int i=1;i<=n;i++)v[i]=false;
edge_ct=0;
DFS_1(1);
return ;
}
int sz[maxn],cc[maxn],gc;
void get_gc(int now,int fa,int size)
{
sz[now]=1;cc[now]=0;
for(int id=head[now];id;id=e[id].next)
{
int j=e[id].to;
if(e[id].ban || j==fa || v[e[id].to])continue;
get_gc(j,now,size);
cc[now]=max(cc[now],sz[j]);
sz[now]+=sz[j];
}
if(size-cc[now]>cc[now])cc[now]=size-cc[now];
if(cc[now]<cc[gc])gc=now;
return ;
}
int dp[maxn],dpct[maxn],_time,Maxdep;
int dp1[maxn],dpct1[maxn];
int ans1,ans2;
void DFS_2(int now,int fa,int de,int sum)
{
sz[now]=1;
if(de>Maxdep)
{
Maxdep=de; dp1[de]=sum; dpct1[de]=1;
}
else
{
if(dp1[de]==sum)dpct1[de]++;
else if(dp1[de]<sum)
{
dp1[de]=sum; dpct1[de]=1;
}
}
for(int id=head[now];id;id=e[id].next)
{
if(e[id].ban || e[id].to==fa || v[e[id].to])continue;
DFS_2(e[id].to,now,de+1,sum+e[id].d);
sz[now]+=sz[e[id].to];
}
return ;
}
int T[maxn];
void calc(int now,int sz)
{
dp[0]=0; dpct[0]=1;
_time++;T[0]=_time;
//for(int i=1;i<=k;i++){dp[i]=-1;dpct[i]=0;}
for(int id=head[now];id;id=e[id].next)
{
if(e[id].ban || v[e[id].to])continue;
Maxdep=0;
DFS_2(e[id].to,now,1,e[id].d);
for(int i=Maxdep;i>=1;i--)
{
if(k-i<0)continue;
if(T[k-i]<_time)
{
dp[k-i]=-1; dpct[k-i]=0; T[k-i]=_time;
}
if(ans1<dp1[i]+dp[k-i])
{
ans1=dp1[i]+dp[k-i]; ans2=dpct[k-i]*dpct1[i];
}
else if(ans1 == dp1[i]+dp[k-i])ans2+=dpct[k-i]*dpct1[i];
}
for(int i=Maxdep;i>=1;i--)
{
if(i>k)continue;
if(T[i]<_time)
{
dp[i]=-1; dpct[i]=0; T[i]=_time;
}
if(dp[i]<dp1[i])
{
dp[i]=dp1[i]; dpct[i]=dpct1[i];
}
else if(dp[i]==dp1[i])
{
dpct[i]+=dpct1[i];
}
}
}
return ;
}
void Tree_Devide(int now,int size)
{
gc=0;cc[0]=oo;
get_gc(now,0,size);
if(gc==0)gc=now;
calc(gc,size);
v[gc]=1;
for(int id=head[gc];id;id=e[id].next)if(!e[id].ban && !v[e[id].to])
{
e[id].ban=e[id+(id%2==0 ? -1 : 1)].ban=true;
if(sz[e[id].to]>=k)Tree_Devide(e[id].to,sz[e[id].to]);
}
return ;
}
void work()
{
ans1=-oo; ans2=0;
_time=0;
memset(v,0,sizeof(v));
Tree_Devide(1,n);
printf("%d %d\n",ans1,ans2);
return ;
}
int main()
{
freopen("in.txt","r",stdin);
Init();
work();
return 0;
}