1. 程式人生 > 實用技巧 >2020杭電多校第2場

2020杭電多校第2場

由於本人水平不夠,這場多校只寫了第1題和第10題

第1題

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6763

Problem A. Total Eclipse   There are n cities and m bidirectional roads in Byteland. These cities are labeled by 1, 2, . . . , n, the   brightness of the i-th city is bi.   Magician Sunset wants to play a joke on Byteland by making a total eclipse such that the brightness of   every city becomes zero. Sunset can do the following operations for arbitrary number of times:     • Select an integer k (1 ≤ k ≤ n).     • Select k distinct cities c1, c2, . . . , ck (1 ≤ ci ≤ n) such that they are connected with each other. Inother words, for every pair of distinct selected cities ci and cj (1 ≤ i < j ≤ k),     if you are at city ci,you can reach city cj without visiting cities not in {c1, c2, . . . , ck}.     • For every selected city ci (1 ≤ i ≤ k), decrease bci by 1.   Now Sunset is wondering what is the minimum number of operations he needs to do, please write aprogram to help him Input
  The fifirst line of the input contains a single integer T (1 ≤ T ≤ 10), the number of test cases.   For each case, the fifirst line of the input contains two integers n and m (1 ≤ n ≤ 100 000, 1 ≤ m ≤ 200 000),denoting the number of cities and the number of roads.   The second line of the input contains n integers b1, b2, . . . , bn (1 ≤ bi ≤ 109 ), denoting the brightness ofeach city.   Each of the following m lines contains two integers ui and vi (1 ≤ ui , vi≤ n, ui= vi), denoting anbidirectional road between the ui-th city and the vi-th city. Note that there may be multiple roads   between the same pair of cities. Output
  For each test case, output a single line containing an integer, the minimum number of operations.

題意:給定一個無向圖,每個點給定權值,每次選擇一個連通塊,將連通塊裡面所有點權值同時減1,直到所有點權值都變成 0,問最少需要幾次

解題思路(官方題解):

    每次一定是選擇一個極大連通塊,將裡面所有數同時減小,直到最小值變成 0,然後將變成 0 的點刪除,分裂成多個連通塊再接著做。     為了實現這個策略,可以將整個過程倒過來看,變成按照 b 的值從大到小依次加入每個點。加入每個點 x 時遍歷與 x 相連的所有邊 (x, y),如果 y 在 x 之前加入且 x 和 y 不連通則將 x   和 y 合併,並將 y 所在連通塊的樹根的父親設為 x,得到一棵有根樹。那麼每個點 x 在成為最   小值之前已經被做了 bfatherx 次操作,所以每個點 x 對答案的貢獻為 bx-bfatherx。     使用並查集支援路徑壓縮,時間複雜度 O((n + m)log n)。 程式碼:
 1
#include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+5; 4 struct node 5 { 6 int id,bi; 7 }ss[N]; 8 int f[N],fa[N],b[N]; 9 bool vis[N]; 10 vector<int > vec[N]; 11 int n,m; 12 int find(int x) 13 { 14 if(f[x]==x)return x; 15 return f[x]=find(f[x]); 16 } 17 void init() 18 { 19 memset(vis,0,sizeof(vis)); 20 memset(fa,0,sizeof(fa)); 21 for(int i=0;i<N;i++) 22 f[i]=i,vec[i].clear(); 23 } 24 bool cmp(struct node x,struct node y) 25 { 26 return x.bi>y.bi; 27 } 28 29 int main() 30 { 31 int t; 32 scanf("%d",&t); 33 while(t--) 34 { 35 init(); 36 scanf("%d%d",&n,&m); 37 for(int i=1;i<=n;i++) 38 { 39 scanf("%d",&b[i]); 40 ss[i].bi=b[i]; 41 ss[i].id=i; 42 } 43 sort(ss+1,ss+1+n,cmp); 44 int u,v,father; 45 for(int i=0;i<m;i++) 46 { 47 scanf("%d%d",&u,&v); 48 vec[u].push_back(v); 49 vec[v].push_back(u); 50 } 51 for(int i=1;i<=n;i++) 52 { 53 u=ss[i].id; 54 vis[u]=1; 55 int len=vec[u].size(); 56 for(int j=0;j<len;j++) 57 { 58 v=vec[u][j]; 59 if(vis[v]==0)continue; 60 father=find(v); 61 if(father==u)continue; 62 fa[father]=f[father]=u; 63 } 64 } 65 long long ans=0; 66 for(int i=1;i<=n;i++) 67 ans+=b[i]-b[fa[i]]; 68 printf("%lld\n",ans); 69 } 70 return 0; 71 }
程式碼

第10題

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6763

Problem J. Lead of Wisdom   In an online game, “Lead of Wisdom” is a place where the lucky player can randomly get powerful items.   There are k types of items, a player can wear at most one item for each type. For the i-th item, it has   four attributes ai , bi , ci and di . Assume the set of items that the player wearing is S, the damage rate of   the player DMG can be calculated by the formula:   Little Q has got n items from “Lead of Wisdom”, please write a program to help him select which itemsto wear such that the value of DMG is maximized. Input   The fifirst line of the input contains a single integer T (1 ≤ T ≤ 10), the number of test cases.   For each case, the fifirst line of the input contains two integers n and k (1 ≤ n, k ≤ 50), denoting thenumber of items and the number of item types.   Each of the following n lines contains fifive integers ti , ai , bi , ci and di (1 ≤ ti ≤ k, 0 ≤ ai , bi , ci , di ≤ 100),   denoting an item of type ti whose attributes are ai , bi , ci and di. Output   For each test case, output a single line containing an integer, the maximum value of DMG. 題意:每組選一個,使DMG最大 題解:暴力 我的程式碼寫的太醜了,這裡就不給出了 官方題解程式碼:
 1 #include<cstdio>
 2 typedef long long ll;
 3 const int N=55;
 4 int Case,n,m,i,j,x,cnt[N],nxt[N],e[N][N][4];ll ans;
 5 void dfs(int x,int a,int b,int c,int d){
 6   if(x>m){
 7     ll tmp=1LL*a*b*c*d;
 8     if(tmp>ans)ans=tmp;
 9     return;
10   }
11   int num=cnt[x];
12   if(!num){
13     dfs(nxt[x],a,b,c,d);
14     return;
15   }
16   for(int i=1;i<=num;i++)dfs(x+1,a+e[x][i][0],b+e[x][i][1],c+e[x][i][2],d+e[x][i][3]);
17 }
18 int main(){
19   scanf("%d",&Case);
20   while(Case--){
21     scanf("%d%d",&n,&m);
22     for(i=1;i<=m;i++)cnt[i]=0;
23     while(n--){
24       scanf("%d",&x);
25       cnt[x]++;
26       for(j=0;j<4;j++)scanf("%d",&e[x][cnt[x]][j]);
27     }
28     x=m+1;
29     for(i=m;i;i--){
30       nxt[i]=x;
31       if(cnt[i])x=i;
32     }
33     ans=0;
34     dfs(1,100,100,100,100);
35     printf("%lld\n",ans);
36   }
37 }
程式碼