• Drivers Dissatisfaction 最小生成树+LCA


    题意:给一张n个点m条边的连通图,每条边(ai,bi)有一个权值wi和费用ci,

    表示这条边每降低1的权值需要ci的花费。现在一共有S费用可以用来降低某些边的权值

    (可以降到负数),求图中的一棵权值和最小的生成树并输出方案

    显然是找到一条边然后将这条边减到最小

    先跑一边最小生成树,找到树上最小的一点,然后在枚举其他的边,

    加上这条边会产生一个环,所以需要删除这个环上面权值最大的边

    这个通过类似于LCA倍增的手法做到,

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <set>
      7 #include <iostream>
      8 #include <map>
      9 #include <stack>
     10 #include <string>
     11 #include <vector>
     12 #define  pi acos(-1.0)
     13 #define  eps 1e-6
     14 #define  fi first
     15 #define  se second
     16 #define  rtl   rt<<1
     17 #define  rtr   rt<<1|1
     18 #define  bug         printf("******
    ")
     19 #define  mem(a,b)    memset(a,b,sizeof(a))
     20 #define  name2str(x) #x
     21 #define  fuck(x)     cout<<#x" = "<<x<<endl
     22 #define  f(a)        a*a
     23 #define  sf(n)       scanf("%d", &n)
     24 #define  sff(a,b)    scanf("%d %d", &a, &b)
     25 #define  sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
     26 #define  sffff(a,b,c,d) scanf("%d %d %d %d", &a, &b, &c, &d)
     27 #define  pf          printf
     28 #define  FRE(i,a,b)  for(i = a; i <= b; i++)
     29 #define  FREE(i,a,b) for(i = a; i >= b; i--)
     30 #define  FRL(i,a,b)  for(i = a; i < b; i++)+
     31 #define  FRLL(i,a,b) for(i = a; i > b; i--)
     32 #define  FIN         freopen("data.txt","r",stdin)
     33 #define  gcd(a,b)    __gcd(a,b)
     34 #define  lowbit(x)   x&-x
     35 using namespace std;
     36 typedef long long  LL;
     37 typedef unsigned long long ULL;
     38 const int mod = 1e9 + 7;
     39 const int maxn = 2e5 + 10;
     40 const int INF = 0x3f3f3f3f;
     41 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
     42 int n, m, c[maxn], w[maxn], fa[maxn], vis[maxn];
     43 int dep[maxn], p[maxn][21], maxx[maxn][21];
     44 struct Edge {
     45     int u, v, w, id;
     46 } edge[maxn];
     47 int cmp ( Edge a, Edge b ) {
     48     return a.w < b.w;
     49 }
     50 struct xxx {
     51     int v, id;
     52     xxx ( int v, int id ) : v ( v ), id ( id ) {}
     53 };
     54 vector<xxx>mp[maxn];
     55 int Find ( int x ) {
     56     return fa[x] == x ? x : fa[x] = Find ( fa[x] );
     57 }
     58 void dfs ( int u, int f, int id ) {
     59     dep[u] = dep[f] + 1, p[u][0] = f, maxx[u][0] = id;
     60     for ( int i = 1 ; i <= 20 ; i++ ) {
     61         if ( dep[u] - ( 1 << i ) <= 0 ) break;
     62         int v = p[u][i - 1];
     63         p[u][i] = p[v][i - 1];
     64         if ( w[maxx[u][i - 1]] < w[maxx[v][i - 1]] ) maxx[u][i] = maxx[v][i - 1];
     65         else maxx[u][i] = maxx[u][i - 1];
     66     }
     67     for ( int i = 0 ; i < mp[u].size() ; i++ ) {
     68         int v = mp[u][i].v, id = mp[u][i].id;
     69         if ( v != f ) dfs ( v, u, id );
     70     }
     71 }
     72 int get_max ( int x, int y ) {
     73     if ( dep[x] < dep[y] ) swap ( x, y );
     74     int temp = 0, ans = 0;
     75     for ( int i = 20 ; i >= 0 ; i-- ) {
     76         if ( dep[x] - ( 1 << i ) >= dep[y] ) {
     77             if ( w[maxx[x][i]] > temp ) ans = maxx[x][i], temp = w[ans];
     78             x = p[x][i];
     79         }
     80     }
     81     if ( x == y ) return ans;
     82     for ( int i = 20 ; i >= 0 ; i-- ) {
     83         if ( dep[x] - ( 1 << i ) > 0 && p[x][i] != p[y][i] ) {
     84             if ( w[maxx[x][i]] > temp ) ans = maxx[x][i], temp = w[ans];
     85             if ( w[maxx[y][i]] > temp ) ans = maxx[y][i], temp = w[ans];
     86             x = p[x][i], y = p[y][i];
     87             if ( x == y ) break;
     88         }
     89     }
     90     if ( w[maxx[x][0]] > temp ) ans = maxx[x][0], temp = w[ans];
     91     if ( w[maxx[y][0]] > temp ) ans = maxx[y][0], temp = w[ans];
     92     return ans;
     93 }
     94 int main() {
     95     sff ( n, m );
     96     for ( int i = 1 ; i <= m ; i++ ) sf ( w[i] );
     97     for ( int i = 1 ; i <= m ; i++ ) sf ( c[i] );
     98     for ( int i = 1 ; i <= m ; i++ ) {
     99         sff ( edge[i].u, edge[i].v );
    100         edge[i].w = w[i], edge[i].id = i;
    101     }
    102     sort ( edge + 1, edge + 1 + m, cmp );
    103     LL sum = 0, s, minn = INF, idx = 0, k = 0;
    104     scanf ( "%lld", &s );
    105     for ( int i = 1 ; i <= n ; i++ ) fa[i] = i;
    106     for ( int i = 1 ; i <= m ; i++ ) {
    107         int nx = Find ( edge[i].v ), ny = Find ( edge[i].u );
    108         if ( nx == ny ) continue;
    109         fa[nx] = ny;
    110         sum += edge[i].w;
    111         vis[edge[i].id] = 1, k++;
    112         if ( c[edge[i].id] < minn )  idx = edge[i].id, minn = c[edge[i].id];
    113         mp[edge[i].u].push_back ( xxx ( edge[i].v, edge[i].id ) );
    114         mp[edge[i].v].push_back ( xxx ( edge[i].u, edge[i].id ) );
    115         if ( k == n - 1 ) break;
    116     }
    117     LL ans = sum - s / minn;
    118     dep[0] = 0;
    119     dfs ( 1, 0, 0 );
    120     int del = 0;
    121     for ( int i = 1 ; i <= m ; i++ ) {
    122         if ( vis[edge[i].id]  ) continue;
    123         int cnt = get_max ( edge[i].u, edge[i].v );
    124         if ( cnt == 0 ) continue;
    125         LL temp = sum - w[cnt] + w[edge[i].id] - s / c[edge[i].id];
    126         if ( temp < ans ) ans = temp,  idx = edge[i].id, del = cnt;
    127     }
    128     if ( del ) vis[del] = 0, vis[idx] = 1;
    129     printf ( "%lld
    ", ans );
    130     w[idx] -= s / c[idx];
    131     for ( int i = 1 ; i <= m ; i++ ) if ( vis[i] ) printf ( "%d %d
    ", i, w[i] );
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    关于XML文档
    Why sql is called structured query language?1
    UML学习---交互
    C#为什么不采用多继承:
    url中
    array
    hard
    构造函数返回值
    布局容器layout Container
    k8s的概念
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/9937041.html
Copyright © 2020-2023  润新知