首先是最短路径树,将一个点相连的所有边装入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; }