zoukankan      html  css  js  c++  java
  • [cf1184E]Daleks' Invasion

    先求出任意一棵最小生成树,然后对边分类讨论
    1.非树边,答案即最小生成树的环上的最长边
    2.树边,反过来考虑,相当于对于每一个点对那条路经打上标记,取min
    对于1直接用倍增维护即可,对于2可以用树链剖分/差分+启发式合并但都需要两个log,所以有一种很神奇的做法
    考虑从小到大枚举非树边,然后暴力修改,容易发现修改过的边就不用修改了,因此复杂度是o(m),问题是如何快速找到没有被修改过的边,可以使用并查集将修改过的边缩起来然后快速往上爬即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define mid (l+r>>1)
     5 struct ji{
     6     int x,y,z,id;
     7 }e[N*10];
     8 struct ji2{
     9     int nex,to,len,id;
    10 }edge[N<<1];
    11 int E,n,m,x,y,head[N],sh[N],ff[N],up[N],vis[N*10],ans[N*10],f[N][21],mx[N][21];
    12 bool cmp(ji x,ji y){
    13     return x.z<y.z;
    14 }
    15 int find(int k){
    16     if (k==ff[k])return k;
    17     return ff[k]=find(ff[k]);
    18 }
    19 void add(int x,int y,int z,int id){
    20     edge[E].nex=head[x];
    21     edge[E].to=y;
    22     edge[E].len=z;
    23     edge[E].id=id;
    24     head[x]=E++;
    25 }
    26 void dfs(int k,int fa,int id,int s){
    27     sh[k]=s;
    28     up[k]=id;
    29     f[k][0]=fa;
    30     for(int i=1;i<=20;i++){
    31         f[k][i]=f[f[k][i-1]][i-1];
    32         mx[k][i]=max(mx[k][i-1],mx[f[k][i-1]][i-1]);
    33     }
    34     for(int i=head[k];i!=-1;i=edge[i].nex)
    35         if (edge[i].to!=fa){
    36             mx[edge[i].to][0]=edge[i].len;
    37             dfs(edge[i].to,k,edge[i].id,s+1);
    38         }
    39 }
    40 pair<int,int> lca(int x,int y){
    41     if (sh[x]<sh[y])swap(x,y);
    42     int ans=0;
    43     for(int i=20;i>=0;i--)
    44         if (sh[f[x][i]]>=sh[y]){
    45             ans=max(ans,mx[x][i]);
    46             x=f[x][i];
    47         }
    48     if (x==y)return make_pair(x,ans);
    49     for(int i=20;i>=0;i--)
    50         if (f[x][i]!=f[y][i]){
    51             ans=max(ans,max(mx[x][i],mx[y][i]));
    52             x=f[x][i];
    53             y=f[y][i];
    54         }
    55     return make_pair(f[x][0],max(ans,max(mx[x][0],mx[y][0])));
    56 }
    57 int main(){
    58     scanf("%d%d",&n,&m);
    59     for(int i=1;i<=m;i++){
    60         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
    61         e[i].id=i;
    62     }
    63     sort(e+1,e+m+1,cmp);
    64     memset(head,-1,sizeof(head));
    65     for(int i=1;i<=n;i++)ff[i]=i;
    66     for(int i=1;i<=m;i++){
    67         x=find(e[i].x);
    68         y=find(e[i].y);
    69         if (x!=y){
    70             ff[x]=y;
    71             add(e[i].x,e[i].y,e[i].z,e[i].id);
    72             add(e[i].y,e[i].x,e[i].z,e[i].id);
    73             vis[i]=1;
    74         }
    75     }
    76     dfs(1,0,0,0);
    77     for(int i=1;i<=m;i++)ans[i]=1000000000;
    78     for(int i=1;i<=n;i++)ff[i]=i;
    79     for(int i=1;i<=m;i++)
    80         if (!vis[i]){
    81             x=lca(e[i].x,e[i].y).first;
    82             ans[e[i].id]=lca(e[i].x,e[i].y).second;
    83             while (find(e[i].x)!=find(x)){
    84                 e[i].x=find(e[i].x);
    85                 ans[up[e[i].x]]=e[i].z;
    86                 if (find(e[i].x)!=find(f[e[i].x][0]))ff[find(e[i].x)]=find(f[e[i].x][0]);
    87             }
    88             while (find(e[i].y)!=find(x)){
    89                 e[i].y=find(e[i].y);
    90                 ans[up[e[i].y]]=e[i].z;
    91                 if (find(e[i].y)!=find(f[e[i].y][0]))ff[find(e[i].y)]=find(f[e[i].y][0]);
    92             }
    93         }
    94     for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    95 }
    View Code
  • 相关阅读:
    关于阿里云带宽监控指标记录
    mongodb备份还原
    squid3.5缓存代理实践记录
    kafka依赖zookeeper原因解析及应用场景
    Zookeeper+Kafka集群部署(转)
    dubbo框架提供Main方法运行容器的几种方式(转)
    html标签简介(常用)
    数据库中和表并列的其他对象
    外键约束
    数据库中的约束
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11842540.html
Copyright © 2011-2022 走看看