挺简单的,但是给人一种把两个问题强行弄到一起的感觉.
十分不好写.
Code:
#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm>
#define N 100007
#define ll long long
#define inf 1000000004
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int K,n,m;
namespace tree
{
ll answer;
int edges,root,sn,maxdep,tl,best;
int hd[N],to[N],nex[N],val[N];
int size[N],mx[N],vis[N],f[N],g[N],bu[N],cntf[N],cntg[N];
void addedge(int u,int v,int c)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
}
void getroot(int u,int ff)
{
size[u]=1,mx[u]=0;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(!vis[v]&&v!=ff)
getroot(v,u), size[u]+=size[v], mx[u]=max(mx[u], size[v]);
}
mx[u]=max(mx[u],sn-size[u]);
if(mx[u]<mx[root]) root=u;
}
void dfs(int u,int ff,int depth,int p)
{
if(depth>=g[p])
{
if(depth==g[p]) ++cntg[p];
else {
if(!g[p]) bu[++tl]=p;
g[p]=depth, cntg[p]=1;
}
}
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff||vis[v]) continue;
dfs(v,u,depth+val[i],p+1);
}
}
void calc(int u)
{
int i,j,cur=0;
cntf[0]=1,tl=0;
for(i=hd[u];i;i=nex[i])
{
int v=to[i];
if(vis[v])
continue;
dfs(v,u,val[i],1);
for(j=cur+1;j<=tl;++j)
{
if(K-1<bu[j]) continue;
if(g[bu[j]]+f[K-bu[j]-1]==best)
{
answer+=(ll)(cntg[bu[j]]*cntf[K-bu[j]-1]);
}
else if(g[bu[j]]+f[K-bu[j]-1]>best)
{
best=g[bu[j]]+f[K-bu[j]-1];
answer=(ll)(cntg[bu[j]]*cntf[K-bu[j]-1]);
}
}
for(j=cur+1;j<=tl;++j)
{
if(g[bu[j]]==f[bu[j]]) cntf[bu[j]]+=cntg[bu[j]];
else if(g[bu[j]]>f[bu[j]])
{
cntf[bu[j]]=cntg[bu[j]];
f[bu[j]]=g[bu[j]];
}
}
for(j=cur+1;j<=tl;++j)
cntg[bu[j]]=g[bu[j]]=0;
cur=tl;
}
for(i=1;i<=cur;++i) cntf[bu[i]]=cntg[bu[i]]=f[bu[i]]=g[bu[i]]=0;
}
void solve(int u)
{
vis[u]=1;
calc(u);
for(int i=hd[u];i;i=nex[i])
if(!vis[to[i]])
sn=size[to[i]],root=0,getroot(to[i],u),solve(root);
}
int main()
{
root=0,mx[0]=inf,sn=n;
getroot(1,0),solve(root);
printf("%d %lld\n",best,answer);
return 0;
}
};
namespace Dijkstra
{
int d[N],done[N],vis[N];
struct Edge
{
int to,val;
Edge(int to=0,int val=0):to(to),val(val){}
};
bool cmp(Edge a,Edge b)
{
return a.to<b.to;
}
struct Node
{
int u,dis;
Node(int u=0,int dis=0):u(u),dis(dis){}
bool operator<(Node a)const
{
return a.dis<dis;
}
};
priority_queue<Node>q;
vector<Edge>G[N];
void add(int u,int v,int c)
{
G[u].push_back(Edge(v,c));
}
void dfs(int u)
{
vis[u]=1;
for(int i=0;i<G[u].size();++i)
if(!vis[G[u][i].to]&&d[u]+G[u][i].val==d[G[u][i].to])
{
vis[G[u][i].to]=1;
tree::addedge(u,G[u][i].to,G[u][i].val);
tree::addedge(G[u][i].to,u,G[u][i].val);
dfs(G[u][i].to);
}
}
void build_tree()
{
int i;
for(i=0;i<=n;++i) d[i]=inf;
q.push(Node(1,0)), d[1]=0;
while(!q.empty())
{
Node e=q.top();q.pop();
int u=e.u;
if(done[u]) continue;
done[u]=1;
for(i=0;i<G[u].size();++i)
{
Edge h=G[u][i];
if(d[h.to]>d[u]+h.val)
{
d[h.to]=d[u]+h.val;
q.push(Node(h.to,d[h.to]));
}
}
}
for(i=1;i<=n;++i) sort(G[i].begin(),G[i].end(),cmp);
dfs(1);
}
};
int main()
{
int i,j;
// setIO("input");
scanf("%d%d%d",&n,&m,&K);
for(i=1;i<=m;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
Dijkstra::add(a,b,c);
Dijkstra::add(b,a,c);
}
Dijkstra::build_tree();
tree::main();
return 0;
}