BZOJ 4016 [FJOI2014]最短路径树问题
题解:构建最短路树,然后在上面点分治
一开始构建的思路是错的但是在Loj上A了
到现在还不明白为什么在BZOJ上T了QWQ,留坑
不要以为自己想的是对的
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=200009; const int oo=1000000000; typedef pair<int,int> fuck; int n,m,k; int d[maxn]; int cntedge=0; int head[maxn]; int to[maxn],nex[maxn],dist[maxn]; void Addedge(int x,int y,int z){ nex[++cntedge]=head[x]; to[cntedge]=y; dist[cntedge]=z; head[x]=cntedge; } vector<fuck>G[maxn]; struct HeapNode{ int v,mindist; HeapNode(int x){ v=x;mindist=d[x]; } bool operator < (const HeapNode &rhs) const{ return mindist>rhs.mindist; } }; priority_queue<HeapNode>q; int caled[maxn]; void Dijkstra(){ for(int i=1;i<=n;++i)d[i]=oo; d[1]=0;q.push(HeapNode(1)); while(!q.empty()){ HeapNode x=q.top();q.pop(); int u=x.v; if(caled[u])continue; caled[u]=1; for(int i=head[u];i;i=nex[i]){ if(d[u]+dist[i]<d[to[i]]){ d[to[i]]=d[u]+dist[i]; q.push(HeapNode(to[i])); } } } } int nowsiz,root; int g[maxn],siz[maxn],dep[maxn]; int vis[maxn]; void Getroot(int x,int fa){ siz[x]=1;g[x]=0; for(int i=head[x];i;i=nex[i]){ if(vis[to[i]])continue; if(to[i]==fa)continue; Getroot(to[i],x); siz[x]+=siz[to[i]]; g[x]=max(g[x],siz[to[i]]); } g[x]=max(g[x],n-siz[x]); if(g[x]<g[root])root=x; } int maxlen=0; long long tot=0; int Tong[maxn][2]; pair<int,int>P[maxn]; int cnt; void Getdep(int x,int fa){ siz[x]=1; dep[x]=dep[fa]+1; ++cnt; P[cnt]=make_pair(dep[x],d[x]); for(int i=head[x];i;i=nex[i]){ if(to[i]==fa)continue; if(vis[to[i]])continue; d[to[i]]=d[x]+dist[i]; Getdep(to[i],x); siz[x]+=siz[to[i]]; } } void Cal(int x){ // printf("Soling %d\n",x); int maxdep=0; d[x]=0;dep[x]=1; Tong[1][0]=0; Tong[1][1]=1; for(int i=head[x];i;i=nex[i]){ if(vis[to[i]])continue; cnt=0; d[to[i]]=dist[i]; Getdep(to[i],x); // for(int j=1;j<=cnt;++j)cout<<P[j].first<<' '<<P[j].second<<endl; for(int j=1;j<=cnt;++j){ int a=P[j].first; int b=P[j].second; maxdep=max(maxdep,a); if(a>k)continue; if(b+Tong[k-a+1][0]>maxlen){ maxlen=b+Tong[k-a+1][0]; tot=Tong[k-a+1][1]; }else if(b+Tong[k-a+1][0]==maxlen){ tot+=Tong[k-a+1][1]; } } for(int j=1;j<=cnt;++j){ int a=P[j].first; int b=P[j].second; if(Tong[a][0]<b){ Tong[a][0]=b; Tong[a][1]=1; }else if(Tong[a][0]==b){ Tong[a][1]++; } } } for(int i=0;i<=maxdep;++i)Tong[i][0]=0,Tong[i][1]=0; // cout<<maxlen<<' '<<tot<<endl; // exit(0); } void Sol(int x){ vis[x]=1; Cal(x); for(int i=head[x];i;i=nex[i]){ if(vis[to[i]])continue; nowsiz=siz[to[i]];root=0; Getroot(to[i],x); Sol(root); } } void Dfs(int x){ caled[x]=1; for(int i=0;i<G[x].size();++i){ fuck e=G[x][i]; if(caled[e.first])continue; Addedge(x,e.first,e.second); Addedge(e.first,x,e.second); Dfs(e.first); } } int main(){ scanf("%d%d%d",&n,&m,&k); while(m--){ int x,y,z; scanf("%d%d%d",&x,&y,&z); Addedge(x,y,z); Addedge(y,x,z); } Dijkstra(); for(int u=1;u<=n;++u){ for(int i=head[u];i;i=nex[i]){ if(d[u]+dist[i]==d[to[i]]){ G[u].push_back(make_pair(to[i],dist[i])); } } sort(G[u].begin(),G[u].end()); } cntedge=0; memset(caled,0,sizeof(caled)); memset(head,0,sizeof(head)); Dfs(1); for(int i=0;i<=n;++i)Tong[i][0]=0,Tong[i][1]=0; nowsiz=n;root=0;g[root]=oo; Getroot(1,0); Sol(root); cout<<maxlen<<' '<<tot<<endl; return 0; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!