• EOJ二月月赛补题


    A:昔我往矣

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

    下附代码:

      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
    ",res);
    109     }
    110     return 0;
    111 }
    View Code

    B:杨柳依依

    对于每组起点终点,bfs求出每个点到他们的最短距离与最短路种数

    那么对于每组起点终点,如果一个点到起点终点的最短路之和与起点终点距离相同,说明该点在最短路上,概率加上 起点开始的种数*终点开始的种数/总的最短路种数

    下附代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int INF=0X3f3f3f3f;
     4 int n,m;
     5 int head[5005],Next[80005],to[80005],tot=0;
     6 double E[5005];
     7 int cnt[2][5005],d[2][5005],b[5005],q[5005];
     8 void add(int a,int b){
     9     Next[tot]=head[a],to[tot]=b;
    10     head[a]=tot++;
    11 }
    12 void bfs(int s,int cnt[],int d[]){
    13     memset(b,0,sizeof(b));
    14         d[s]=0,cnt[s]=1;
    15         int r=1,l=0;
    16         q[r]=s;
    17         while (l<=r){
    18             int x=q[++l];
    19             if (b[x]) continue;
    20             b[x]=1;
    21             for (int i=head[x]; i!=-1; i=Next[i]){
    22                 int y=to[i];
    23                 if (d[y]>d[x]+1){
    24                     d[y]=d[x]+1;
    25                     cnt[y]=cnt[x];
    26                         q[++r]=y;
    27                 }
    28                 else if (d[y]==d[x]+1){
    29                     cnt[y]+=cnt[x];
    30                 }
    31             }
    32         }
    33 }
    34 int main(){
    35     scanf("%d%d",&n,&m);
    36     for (int i=0; i<n; i++) head[i]=-1;
    37     for (int i=1; i<=m; i++){
    38         int x,y;
    39         scanf("%d%d",&x,&y);
    40         add(x,y);
    41         add(y,x);
    42     }
    43     int T;
    44     scanf("%d",&T);
    45     while (T--){
    46         int st,ed;
    47         scanf("%d%d",&st,&ed);
    48         memset(cnt,0,sizeof(cnt));
    49         memset(d,INF,sizeof(d));
    50         bfs(st,cnt[0],d[0]);
    51         bfs(ed,cnt[1],d[1]);
    52         if (d[0][ed]==INF) continue;
    53         for (int i=0; i<n; i++){
    54             if (d[0][i]+d[1][i]==d[0][ed]){
    55                 E[i]+=1.0*cnt[0][i]*cnt[1][i]/cnt[0][ed];
    56             }
    57         }
    58     }
    59     double maxn=-INF;
    60     int pos;
    61     for (int i=0; i<n; i++){
    62         if (E[i]>maxn){
    63             maxn=E[i];
    64             pos=i;
    65         }
    66     }
    67     printf("%d
    ",pos);
    68 }
    View Code
  • 相关阅读:
    python每日一题:使用套接字创建分布式进程
    市盈率分析
    python每日一题:分布式进程之坑点
    python每日一题:比较单线程,多线程,协程的运行效率
    python每日一题:锁知识点
    python每日一题:查找一篇文档中的人名和城市
    python之装饰器@
    python每日一题:利用字典实现超市购物程序
    【Java基础】多线程
    【Java基础】异常处理
  • 原文地址:https://www.cnblogs.com/i-caigou-TT/p/14400226.html
Copyright © 2020-2023  润新知