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
  • 相关阅读:
    day 66 ORM django 简介
    day 65 HTTP协议 Web框架的原理 服务器程序和应用程序
    jQuery的事件绑定和解绑 事件委托 轮播实现 jQuery的ajax jQuery补充
    background 超链接导航栏案例 定位
    继承性和层叠性 权重 盒模型 padding(内边距) border(边框) margin 标准文档流 块级元素和行内元素
    属性选择器 伪类选择器 伪元素选择器 浮动
    css的导入方式 基础选择器 高级选择器
    03-body标签中相关标签
    Java使用内存映射实现大文件的上传
    正则表达式
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11842540.html
Copyright © 2011-2022 走看看