zoukankan      html  css  js  c++  java
  • Codeforces Round #378 (Div. 2) F

    F - Drivers Dissatisfaction

    题目大意:给你n个点,m条边,每个边都有一个权重w,每条边也有一个c表示,消耗c元可以把这条边的权重减1,求最多消耗s元的最小生成树。

    思路:因为一条边的权重没有下限所以s元肯定是用在一条边上的。 那么我们先跑一个最小生成树,把这棵最小生成树建出来,然后我们枚举用了

    s元之后的边,如果这条边不在树上那么加上这条边之后肯定形成了一个环,最优的方案肯定是删掉这个环中权值最大的边再次变成一棵树。

    对于边(u,v)来说,如果把这条边加上,那么删掉的边肯定在,u到 lca(u,v) 和 v到 lca(u,v)中的权值最大的那条边。 可以用倍增快速找边,就能解决

    这个问题啦。  码起来好麻烦啊,借鉴了某个学长的代码。。

      1 #include<bits/stdc++.h>
      2 #define fi first
      3 #define se second
      4 #define mk make_pair
      5 #define ll long long
      6 #define pll pair<ll,ll>
      7 #define pil pair<int,ll>
      8 #define pli pair<ll,int>
      9 #define pii pair<int,int>
     10 #define read(x) scanf("%d",&x)
     11 #define sread(x) scanf("%s",x)
     12 #define dread(x) scanf("%lf",&x)
     13 #define lread(x) scanf("%lld",&x)
     14 using namespace std;
     15 
     16 const int N=2e5+7;
     17 const int M=2e6+7;
     18 const int inf=0x3f3f3f3f;
     19 const ll INF=0x3f3f3f3f3f3f3f3f;
     20 const int mod=1e9+7;
     21 
     22 int n,m,tot,s,fa[N],depth[N],nx[N][20],mx[N][20];
     23 
     24 struct node
     25 {
     26     int u,v,w,c,id;
     27     bool operator < (const node &rhs)const
     28     {
     29         return w<rhs.w;
     30     }
     31 }e[N<<1];
     32 
     33 bool cmp(node a,node b){
     34     return a.id<b.id;
     35 }
     36 vector<pii> edge[N];
     37 map<int,int> result;
     38 
     39 int Find(int x) {
     40     return x==fa[x]? x : fa[x]=Find(fa[x]);
     41 }
     42 
     43 ll kruscal()
     44 {
     45     ll ans=0;
     46     for(int i=1;i<=n;i++)
     47         fa[i]=i;
     48 
     49     sort(e,e+m);
     50 
     51     for(int i=0;i<m;i++)
     52     {
     53         int u=e[i].u,v=e[i].v,w=e[i].w;
     54         int nx_u=Find(u);
     55         int nx_v=Find(v);
     56         if(nx_u!=nx_v)
     57         {
     58             edge[u].push_back(mk(v,e[i].id));
     59             edge[v].push_back(mk(u,e[i].id));
     60 
     61             fa[nx_u]=nx_v;
     62             ans+=w;
     63             result[e[i].id]=w;
     64         }
     65     }
     66 
     67     sort(e,e+m,cmp);
     68 
     69     return ans;
     70 }
     71 
     72 int getMxId(int a,int b)
     73 {
     74     if(a==-1) return b;
     75     if(b==-1) return a;
     76     return e[a].w>e[b].w? a : b;
     77 }
     78 void dfs(int u,int pre)
     79 {
     80     nx[u][0]=pre;
     81     for(int i=1;i<20;i++)
     82     {
     83         if(nx[u][i-1]!=-1)
     84         {
     85             nx[u][i]=nx[nx[u][i-1]][i-1];
     86             mx[u][i]=getMxId(mx[u][i-1],mx[nx[u][i-1]][i-1]);
     87         }
     88         else
     89             nx[u][i]=mx[u][i]=-1;
     90     }
     91 
     92     for(auto t : edge[u])
     93     {
     94         int v=t.first;
     95         if(v==pre)
     96             continue;
     97         depth[v]=depth[u]+1;
     98         mx[v][0]=t.second;
     99 
    100         dfs(v,u);
    101     }
    102 }
    103 
    104 int getLca(int a,int b)
    105 {
    106     if(depth[a]<depth[b])
    107         swap(a,b);
    108     for(int i=0;i<20;i++)
    109         if(depth[a]-depth[b]>>i & 1)
    110             a=nx[a][i];
    111 
    112     if(a==b) return a;
    113     for(int i=19;i>=0;i--)
    114         if(nx[a][i]!=nx[b][i])
    115             a=nx[a][i],b=nx[b][i];
    116 
    117     return nx[a][0];
    118 }
    119 
    120 int getMxIdPath(int a,int b)
    121 {
    122     int lca=getLca(a,b);
    123     int ret=-1;
    124     for(int i=19;i>=0;i--)
    125     {
    126         if(nx[a][i]!=-1 && depth[nx[a][i]]>=depth[lca])
    127         {
    128             ret=getMxId(ret,mx[a][i]);
    129             a=nx[a][i];
    130         }
    131         if(nx[b][i]!=-1 && depth[nx[b][i]]>=depth[lca])
    132         {
    133             ret=getMxId(ret,mx[b][i]);
    134             b=nx[b][i];
    135         }
    136     }
    137     return ret;
    138 }
    139 
    140 int main()
    141 {
    142     read(n); read(m);
    143 
    144     for(int i=0;i<m;i++)
    145         read(e[i].w);
    146 
    147     for(int i=0;i<m;i++)
    148         read(e[i].c);
    149 
    150     for(int i=0;i<m;i++)
    151     {
    152         read(e[i].u);
    153         read(e[i].v);
    154         e[i].id=i;
    155     }
    156 
    157     read(s);
    158 
    159     ll cost=kruscal();
    160 
    161     dfs(1,-1);
    162 
    163     ll ans=cost, p=0;
    164 
    165     for(int id=0;id<m;id++)
    166     {
    167         int big=getMxIdPath(e[id].u,e[id].v);
    168         ll tmp=cost-e[big].w+e[id].w-s/e[id].c;
    169         if(tmp<ans)
    170             ans=tmp,p=id;
    171     }
    172 
    173     printf("%lld
    ",ans);
    174     result.erase(getMxIdPath(e[p].u,e[p].v));
    175     result[p]=e[p].w-s/e[p].c;
    176 
    177     for(auto t: result)
    178         printf("%d %d
    ",t.first+1,t.second);
    179 
    180     return 0;
    181 }
    182 /*
    183 */
  • 相关阅读:
    android的UriMatcher类
    学习Scanner类
    android应用开发 listview
    EditText 和 TextView 的属性详解
    Android适配器Adapter学习
    AlertDialog.Builder对话框类的用法
    Android ArrayAdapter 详解
    ThreadPoolExecutor线程池大小设置与BlockingQueue的三种实现区别
    【Android】滑动屏幕效果GestureDetector、OnGestureListener、ViewFlipper
    Windows Phone 7常用的开发技巧&学习总结
  • 原文地址:https://www.cnblogs.com/CJLHY/p/8676162.html
Copyright © 2011-2022 走看看