Total Eclipse HDU - 6763
Practice link: https://vjudge.net/problem/HDU-6763
题目描述
Problem Description
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. In other 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.
Note that Sunset will always choose k with the maximum possible value. Now Sunset is wondering what is the minimum number of operations he needs to do, please write a program to help him.Input
The first line of the input contains a single integer T (1≤T≤10), the number of test cases.
For each case, the first line of the input contains two integers n and m (1≤n≤100000, 1≤m≤200000), 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 of each city.
Each of the following m lines contains two integers ui and vi (1≤ui,vi≤n,ui≠vi), denoting an bidirectional 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.
题意:给你 n 个值表示每个点的权值,再给你一些边即构成了几个连通块,你可以选择 k 个连通的点进行一次操作,让这 k 个点的权值 -1,问你最少需要几次操作。
思路:我们先对每个点的权值进行排序,然后用逆向思维进行加边,用并查集进行合并,首先将某个点的权值 a[ i ]加入 ans ,然后找如果有另外一个点与这个点有边但未进行合并且在此之前已经加入了 ans,由于我们对点权进行了排序,则说明这个点的权值比a[ i ] 大,就说明可以在加值的过程中 a[ i ]可以与这个点共同进行,那么 ans= ans - a [ i ]。以此类推,就是最少操作数。
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define MOD 998244353 4 #define INF 0x3f3f3f3f 5 #define mem(a,x) memset(a,x,sizeof(a)) 6 #define _for(i,a,b) for(int i=a; i< b; i++) 7 #define _rep(i,a,b) for(int i=a; i<=b; i++) 8 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 9 using namespace std; 10 const int maxn = 100000; 11 int fa[maxn+5]; 12 int vis[maxn+5]; 13 int a[maxn+5]; 14 vector<int>g[maxn+5]; 15 int n,m; 16 ll ans; 17 struct IN{ 18 int id,w; 19 }ss[maxn+5]; 20 bool cmp(IN x,IN y){ 21 return x.w>y.w; 22 } 23 int find(int x) 24 { 25 return (fa[x]==x)?x:(fa[x]=find(fa[x])); 26 } 27 void merge(int i,int j) 28 { 29 int x=i; 30 int y=find(j); 31 fa[y]=x; 32 } 33 int main() 34 { 35 int t; 36 scanf("%d",&t); 37 while(t--){ 38 ans=0; 39 scanf("%d %d",&n,&m); 40 for(int i=1;i<=n;i++){ 41 scanf("%d",&ss[i].w); 42 fa[i]=i; 43 a[i]=ss[i].w; 44 ss[i].id=i; 45 g[i].clear(); 46 vis[i]=0; 47 } 48 for(int i=1;i<=m;i++){ 49 int u,v; 50 scanf("%d %d",&u,&v); 51 g[u].push_back(v); 52 g[v].push_back(u); 53 } 54 sort(ss+1,ss+n+1,cmp); 55 for(int j=1;j<=n;j++){ 56 int now=ss[j].id; 57 ans+=a[now]; 58 vis[now]=1; 59 for(int i=0;i<g[now].size();i++){ 60 int v=g[now][i]; 61 if(!vis[v]||find(v)==find(now))continue; 62 merge(v,now); 63 ans-=a[now]; 64 } 65 } 66 cout<<ans<<endl; 67 } 68 return 0; 69 } 70 71 /*8 5 72 1 3 6 5 4 2 1 1 73 1 7 74 3 1 75 6 3 76 5 8 77 2 4 */
越自律,越自由