EOJ二月月赛补题

A:昔我往矣

lca+dfs序,先做出所有点的dfs序,然后对于每一个询问,以dfs序最小和最大的为两个端点,然后往里面加点相当于加上一条分叉出去的链,用LCA求解即可。

下附代码:

EOJ二月月赛补题
  1 #include<bits/stdc++.h>
  2 #define ll long long
  3 using namespace std;
  4 const ll INF=0X3f3f3f3f3f3f3f3f;
  5 int Next[100005],to[100005];
  6 ll len[100005];
  7 int head[50005];
  8 ll tot=0;
  9 int dep[50005],f[50005][20];
 10 ll l[50005][20],n,q;
 11 int a[10];
 12 int dfn[50005],cnt;
 13 struct node{
 14     ll p,l;
 15 };
 16 bool cmp(int x,int y){
 17     return dfn[x]<dfn[y];
 18 }
 19 inline void add(int a,int b,ll c){
 20     Next[tot]=head[a],to[tot]=b,len[tot]=c;
 21     head[a]=tot++;
 22 }
 23 inline void deal(ll x,ll fa){
 24     dep[x]=dep[fa]+1;
 25     for (int i=0; i<=16; i++){
 26         f[x][i+1]=f[f[x][i]][i];
 27         l[x][i+1]=l[x][i]+l[f[x][i]][i];
 28     }
 29     for (int i=head[x]; i!=-1; i=Next[i]){
 30         int y=to[i];
 31         if (y==fa) continue;
 32         f[y][0]=x;
 33         l[y][0]=len[i];
 34         deal(y,x);
 35     }
 36 }
 37 void dfs(int x,int pre){
 38     if (dfn[x]!=0) return;
 39     dfn[x]=++cnt;
 40     for (int i=head[x]; i!=-1; i=Next[i]){
 41         int y=to[i];
 42         if (y!=pre){
 43             dfs(y,x);
 44         }
 45     }
 46 }
 47 inline node lca(int x,int y){
 48     int tmp=x;
 49     ll ret=0;
 50     if (dep[x]<dep[y]) swap(x,y);
 51     for (int i=16; i>=0; i--){
 52         if (dep[f[x][i]]>=dep[y])  {
 53             ret+=l[x][i];
 54             x=f[x][i];
 55         }
 56         if (x==y) {
 57             return {y,ret};
 58         }
 59     }
 60     for (int i=16; i>=0; i--){
 61         if (f[x][i]!=f[y][i]){
 62             ret=ret+l[x][i];
 63             ret=ret+l[y][i];
 64             x=f[x][i];
 65             y=f[y][i];
 66         }
 67     }
 68     ret+=l[x][0]+l[y][0];
 69     return {f[x][0],ret};
 70 }
 71 int main(){
 72     scanf("%lld",&n);
 73     for (int i=0; i<n; i++){
 74         head[i]=-1;
 75     }
 76     for (int i=1; i<n; i++){
 77         ll a,b,c;
 78         scanf("%lld%lld%lld",&a,&b,&c);
 79         add(a,b,c);
 80         add(b,a,c);
 81     }
 82     deal(0,-1);
 83     scanf("%lld",&q);
 84     cnt=0;
 85     dfs(0,-1);
 86     while (q--){
 87         for (int i=1; i<=5; i++){
 88             scanf("%lld",&a[i]);
 89         }
 90         sort(a+1,a+6,cmp);
 91         node p=lca(a[1],a[5]);
 92         ll res=p.l;
 93         vector<int> now;
 94         now.push_back(a[1]);
 95         now.push_back(a[5]);
 96         for (int i=2; i<=4; i++){
 97             int maxn=0,pp=0;
 98             for (auto j:now){
 99                 node p1=lca(a[i],j);
100                 if (dep[p1.p]>maxn){
101                     maxn=dep[p1.p];
102                     pp=p1.p;
103                 }
104             }
105             res+=lca(pp,a[i]).l;
106             now.push_back(a[i]);
107         }
108         printf("%lld\n",res);
109     }
110     return 0;
111 }
View Code

 

上一篇:C# - 静态类和静态构造函数


下一篇:EOJ 7月月赛