1. 程式人生 > 實用技巧 >Total Eclipse HDU - 6763

Total Eclipse HDU - 6763

Practice link:https://vjudge.net/problem/HDU-6763

題目描述

Problem Description

There arencities andmbidirectional roads in Byteland. These cities are labeled by1,2,,n, the brightness of thei-th city isbi.

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 integerk(1kn).

· Selectkdistinct citiesc1,c2,,ck(1cin) such that they are connected with each other. In other words, for every pair of distinct selected citiesciandcj(1i<jk), if you are at cityci, you can reach citycjwithout visiting cities not in{c1,c2,,ck}
.

· For every selected cityci(1ik), decreasebciby1.

Note that Sunset will always choosekwith 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 integerT
(1T10), the number of test cases.

For each case, the first line of the input contains two integersnandm(1n100000,1m200000), denoting the number of cities and the number of roads.

The second line of the input containsnintegersb1,b2,,bn(1bi109), denoting the brightness of each city.

Each of the followingmlines contains two integersuiandvi(1ui,vin,uivi), denoting an bidirectional road between theui-th city and thevi-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   */
View Code