2020杭電多校第2場
阿新 • • 發佈:2020-07-24
由於本人水平不夠,這場多校只寫了第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題意:給定一個無向圖,每個點給定權值,每次選擇一個連通塊,將連通塊裡面所有點權值同時減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 }程式碼