• Codeforces Round #378 (Div. 2)F


    题目:一个带权连通无向图,给第i条边权值减1需要花费ci元,你一共有S元,求最小生成树。

    容易得出钱全部花在一条边上是最优的。

    我们先做一遍最小生成树。

    然后我们枚举减哪一条边。

    如果这条边是树上的,那么直接得出答案。

    如果不是,我们可以用这一条边去替换u[i]、v[i]路径之间任意一条。所以我们用倍增(我sb了用的树链剖分)找到路径上最大的那一条替换,计算答案。

    最后把这条边放进树里,再求一遍最小生成树就能输出方案了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define MAX(a,b) a>b?a:b
      5 #define N 210000 
      6 #define M 210000
      7 #define mem(a) memset(a,0,sizeof(a))
      8 #define rep(i,n) for (int i=1;i<=(n);i++)
      9 #define LL long long
     10 using namespace std;
     11 int uu,vv,root,ee,rr,ll,_,n,tot,e[M<<1],head[N],nex[N<<1];
     12 int id,p,q,m,top[N],siz[N],s[N],d[N],w[N],f[N],l[N<<2],r[N<<2];
     13 LL fuck,a[N<<2],orz,sum,S,ans,ma;
     14 bool intree[M];
     15 struct lbz
     16 {
     17     int u,v,d;
     18     LL w,c;
     19 }ed[M];
     20 void add(int u,int v,int c)
     21 {
     22     e[++ee]=v;nex[ee]=head[u];head[u]=ee;
     23 }
     24 void build(int s,int ll,int rr)
     25 {
     26     l[s]=ll;r[s]=rr; 
     27     if (ll==rr)
     28         a[s]=0;
     29     else
     30     {
     31         int mid=(ll+rr)>>1;
     32         build(s<<1,ll,mid);
     33         build((s<<1)+1,mid+1,rr);    
     34     }
     35 }
     36 void add(int s)
     37 {
     38     if (l[s]==r[s])
     39         a[s]=rr;
     40     else
     41     {
     42         if (r[s<<1]>=ll)
     43             add(s<<1);
     44         else
     45             add((s<<1)+1);
     46         a[s]=MAX(a[s<<1],a[(s<<1)+1]);
     47     }
     48 }
     49 void sea(int s)
     50 {
     51     if (l[s]>rr || r[s]<ll)
     52         return;
     53     if (l[s]>=ll&&r[s]<=rr)
     54         ans=MAX(ans,a[s]);
     55     else
     56     {
     57         sea(s<<1);
     58         sea((s<<1)+1);
     59     }
     60 }
     61 void dfs1(int u)
     62 {
     63     int j=head[u];
     64     siz[u]=1;
     65     while (j>0)
     66     {
     67         if (d[e[j]]==0)
     68         {
     69             d[e[j]]=d[u]+1;
     70             f[e[j]]=u;
     71             dfs1(e[j]);
     72             if (siz[e[j]]>siz[s[u]])
     73                 s[u]=e[j];
     74             siz[u]+=siz[e[j]];
     75         }
     76         j=nex[j];
     77     }
     78 }
     79 void dfs2(int u)
     80 {
     81     int j=head[u];
     82     if (s[u]!=0)
     83     {
     84         w[s[u]]=++tot;
     85         top[s[u]]=top[u];
     86         dfs2(s[u]);
     87     }
     88     while (j>0)
     89     {
     90         if (e[j]!=s[u]&&e[j]!=f[u])
     91         {
     92             w[e[j]]=++tot;
     93             top[e[j]]=e[j];
     94             dfs2(e[j]);
     95         }
     96         j=nex[j];
     97     }
     98 }
     99 void init()
    100 {
    101     orz=sum;
    102     id=1;
    103     mem(f);
    104 }
    105 bool cmp(lbz a,lbz b)
    106 {
    107     return a.w<b.w;
    108 }
    109 int find(int x)
    110 {
    111     if (f[x]==0) return x;
    112     f[x]=find(f[x]);
    113     return f[x];
    114 }
    115 int main()
    116 {
    117     scanf("%d%d",&n,&m);
    118     rep(i,m)
    119         scanf("%I64d",&ed[i].w);
    120     rep(i,m)
    121         scanf("%I64d",&ed[i].c);
    122     rep(i,m)
    123         scanf("%d%d",&ed[i].u,&ed[i].v);
    124     scanf("%I64d",&S);
    125     rep(i,m)
    126         ed[i].d=i;
    127     sort(ed+1,ed+1+m,cmp);
    128     rep(i,m)
    129     {
    130         p=find(ed[i].u);
    131         q=find(ed[i].v);
    132         if (p!=q)
    133         {
    134             f[p]=q;
    135             intree[i]=1;    
    136             sum+=ed[i].w;
    137         }
    138     }
    139     init();
    140     rep(i,m)
    141         if (intree[i]==1)
    142         {
    143             add(ed[i].u,ed[i].v,ed[i].w);
    144             add(ed[i].v,ed[i].u,ed[i].w);
    145         }
    146     build(1,1,n-1);    
    147     root=1;d[root]=1;top[root]=root;
    148     dfs1(root);
    149     dfs2(root);
    150     rep(i,m)
    151     {
    152         if (intree[i]==0)continue;
    153         if (d[ed[i].u]>d[ed[i].v])
    154             swap(ed[i].u,ed[i].v);
    155         ll=w[ed[i].v];rr=ed[i].w;
    156         add(1);
    157     }    
    158     rep(i,m)
    159     {
    160         if (intree[i]==1)
    161         {
    162             fuck=sum-S/ed[i].c;
    163             if (fuck<orz)
    164             {
    165                 orz=fuck;
    166                 id=i;
    167             }
    168             continue;
    169         }
    170         uu=ed[i].u;vv=ed[i].v;
    171         ma=0;
    172         while (top[uu]!=top[vv])
    173         {
    174             if (d[top[uu]]<d[top[vv]])
    175                 swap(uu,vv);
    176             ans=0;ll=w[top[uu]];rr=w[uu];sea(1);
    177             ma=MAX(ma,ans);
    178             uu=f[top[uu]];
    179         }
    180         if (uu!=vv)
    181         {
    182             if (d[uu]<d[vv]) swap(uu,vv);
    183             ans=0;ll=w[s[vv]];rr=w[uu];sea(1);
    184             ma=MAX(ma,ans);
    185         }
    186         fuck=sum-ma+ed[i].w-S/ed[i].c;
    187         if (fuck<orz)
    188         {
    189             orz=fuck;
    190             id=i;
    191         }
    192     }
    193     mem(f);mem(intree);
    194     ed[id].w-=S/ed[id].c;
    195     sort(ed+1,ed+1+m,cmp);
    196     rep(i,m)
    197     {
    198         p=find(ed[i].u);
    199         q=find(ed[i].v);
    200         if (p!=q)
    201         {
    202             f[p]=q;
    203             intree[i]=1;    
    204         }
    205     }
    206     printf("%I64d
    ",orz);
    207     rep(i,m)
    208         if (intree[i])
    209             printf("%d %I64d
    ",ed[i].d,ed[i].w);
    210     return 0;
    211         
    212 }
    View Code
    #WhenWhoProblemLangVerdictTimeMemory
    22090610 2016-11-07 11:28:10 lbz007 F - Drivers Dissatisfaction GNU C++ Accepted 608 ms 34700 KB
    ------------------------------------------------------------------------- 花有重开日,人无再少年
  • 相关阅读:
    Ubuntu驱动程序开发2-Uboot命令使用
    Ubuntu驱动程序开发1-环境搭建
    STM32F4 串口IAP程序解析
    QT样式表(QSS)
    设备树常用OF函数
    UCOSIII在STM32f4上面的移植
    UCOS常用函数API
    MySQL学习——备份和还原
    JavaWeb学习——页面跳转方式
    Java问题记录——循环里的二次判断与状态更新
  • 原文地址:https://www.cnblogs.com/lbz007oi/p/6039480.html
Copyright © 2020-2023  润新知