• 【FJOI2014】最短路径树问题


    题面

    https://www.luogu.org/problem/P2993

    题解

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define ri register int
    #define N 30500
    #define INF 10000000000007LL
    #define LL long long
    using namespace std;
    int n,m,k,cc=0;
    vector<int> to[N],t[N],len[N],l[N];
    int siz[N],b[N],bb[N];
    bool vis[N];
    LL dis[N],av=0,ac=0,a[N],aa[N];
    
    LL A(int x) {
      if (x>=0) return a[x]; else return -1000000007;
    }
    
    struct node{
      int v; LL d;
      bool operator < (const node &rhs) const {
        if (d==rhs.d) return v>rhs.v; else return d>rhs.d;
      }
    };
    
    void addedge(int x,int y,int z){
      t[x].push_back(y); l[x].push_back(z);
      //t[y].push_back(x); l[y].push_back(z);
    }
    
    void dij() {
      for (ri i=1;i<=n;i++) dis[i]=INF;
      dis[1]=0;
      priority_queue<node> q;
      q.push((node){1,0});
      while (!q.empty()) {
        int x=q.top().v; q.pop();
        if (vis[x]) continue;
        vis[x]=1;
        for (ri i=0,ls=to[x].size();i<ls;i++) {
          int v=to[x][i];
          if (dis[x]+len[x][i]<dis[v]) {
            dis[v]=dis[x]+len[x][i];
            q.push((node){v,dis[v]});
          }
        }
      }
    }
    
    void build() {
      memset(vis,0,sizeof(vis));
      vis[1]=1;
      priority_queue<node> q;
      while (!q.empty()) q.pop();
      q.push((node){1,0});
      while (!q.empty()) {
        int x=q.top().v; q.pop();
        for (ri i=0,ls=to[x].size();i<ls;i++) if (dis[to[x][i]]==dis[x]+len[x][i] && !vis[to[x][i]]) {
          //cout<<x<<" "<<to[x][i]<<endl;
          cc++;
          vis[to[x][i]]=1;
          addedge(x,to[x][i],len[x][i]);
          addedge(to[x][i],x,len[x][i]);
          q.push((node){to[x][i],dis[to[x][i]]});
        }
      }
    }
    
    void findroot(int x,int ff,int &rt,int &rts,int tot) {
      int curs=0;
      siz[x]=1;
      for (ri i=0,ls=t[x].size();i<ls;i++) if (t[x][i]!=ff && !vis[t[x][i]]) {
        findroot(t[x][i],x,rt,rts,tot);
        if (siz[t[x][i]]>curs) curs=siz[t[x][i]];
        siz[x]+=siz[t[x][i]];
      }
      if (tot-siz[x]>curs) curs=tot-siz[x];
      if (curs<rts) rts=curs,rt=x;
    }
    
    void tonji(int x,int ff,int d,LL w,int &maxd) {
      if (w>aa[d]) aa[d]=w,bb[d]=0;
      if (w==aa[d]) bb[d]++;
      if (d>maxd) maxd=d;
      for (ri i=0,ls=t[x].size();i<ls;i++) if (t[x][i]!=ff && !vis[t[x][i]]) tonji(t[x][i],x,d+1,w+l[x][i],maxd);
    }
    
    void cnt(int x,int ff,int &tot) {
      tot++;
      for (ri i=0,ls=t[x].size();i<ls;i++) if (t[x][i]!=ff && !vis[t[x][i]]) cnt(t[x][i],x,tot);
    }
    
    void solve(int x) {
      // a[x] d==x maxw value
      // b[x] d==x maxw times
      a[0]=0; b[0]=1;
      vis[x]=1;
      int md=0;
      for (ri i=0,ls=t[x].size();i<ls;i++) if (!vis[t[x][i]]) {
        int maxd=0;
        tonji(t[x][i],x,1,l[x][i],maxd);
        md=max(md,maxd);
        //printf("%d %d %d
    ",i,t[x][i],maxd);
        for (ri j=1;j<=maxd;j++) if (aa[j]+A(k-j-1)>av) av=aa[j]+A(k-j-1),ac=0;
        for (ri j=1;j<=maxd;j++) if (aa[j]+A(k-j-1)==av) {
          ac+=bb[j]*1LL*b[k-j-1];
          //printf("x=%d s=%d aa[%d]=%lld a[%d]=%lld bb[%d]=%d b[%d]=%d
    ",x,t[x][i],j,aa[j],k-j-1,a[k-j-1],j,bb[j],k-j-1,b[k-j-1]);
          //cout<<x<<" "<<aa[j]<<" "<<a[k-j-1]<<" "<<bb[j]<<" "<<b[k-j-1]<<endl;
        }
        for (ri j=1;j<=maxd;j++) {
          if (aa[j]>a[j]) a[j]=aa[j],b[j]=0;
          if (aa[j]==a[j]) b[j]+=bb[j];
        }
        for (ri j=1;j<=maxd;j++) aa[j]=0,bb[j]=0;
      }
    
      for (ri i=0;i<=md;i++) a[i]=0,b[i]=0;
    
      for (ri i=0,ls=t[x].size();i<ls;i++) if (!vis[t[x][i]]) {
        int tot=0;
        cnt(t[x][i],x,tot);
        int rt=-1,rts=tot;
        findroot(t[x][i],x,rt,rts,tot);
        solve(rt);
      }
    }
    
    void dianfen() {
      memset(vis,0,sizeof(vis));
      int rt=-1,rts=n;
      findroot(1,1,rt,rts,n);
      solve(rt);
    }
    
    int main(){
      int a,b,c;
      scanf("%d %d %d",&n,&m,&k);
      for (ri i=1;i<=m;i++) {
        scanf("%d %d %d",&a,&b,&c);
        to[a].push_back(b); len[a].push_back(c);
        to[b].push_back(a); len[b].push_back(c);
      }
      dij();
      build();
      dianfen();
      printf("%lld %lld
    ",av,ac);
    }
  • 相关阅读:
    k8s二进制安装
    jenkins
    Deploy Apollo on Kubernetes
    Apollo配置中心搭建常见报错
    Apollo配置中心搭建过程
    使用CephRBD为Kubernetes提供StorageClass
    Ceph基础命令总结
    Ceph分布式存储系统搭建
    zabbix入门之配置邮件告警
    zabbix入门之定义触发器
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11278517.html
Copyright © 2020-2023  润新知