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
原文地址:https://www.cnblogs.com/qldabiaoge/p/9937041.html