Total Eclipse
题目大意
给一个无向图,有点权。
每次选一整个连通块,让这个连通块里的点权都减一,问最少操作几步可以让他们都减成0? 减成0了就不能再减了,也就是这个点就删去了。
题意给的不明确。他没说选的连通块尽可能大。。结果到最后了改了题面说连通块必须选尽可能大的。可是,,选尽可能大的,哪来的最小操作次数。。操作次数不就是一样的吗。。这是出题人的锅
比如这个样例,如果必须选最大的连通块,那么答案是12,如果不用选最大的,答案是8。
但是后来发现这个就算是选尽可能大的连通块,我也不一定会。。
我好菜
题解
减的话,是会先把最小值减成0,然后这个点这里断开,继续选最小的。
直接减肯定会超时的。
然后 这个怎么算答案呢。
可以反过来想,然后每次先把最大的给加上,加一个点的时候,看一下直接与他相连的点有没有加进去,如果加进去了,那点权肯定比他大。直接合并,
代码:
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <cmath>
#include <set>
#include <cstring>
#include <string>
#include <unordered_set>
#include <bitset>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef unsigned long long ull;
typedef set<int>::iterator sit;
#define st first
#define sd second
#define mkp make_pair
#define pb push_back
void wenjian(){
freopen("concatenation.in","r",stdin);freopen("concatenation.out","w",stdout);}
void tempwj(){
freopen("hash.in","r",stdin);freopen("hash.out","w",stdout);}
ll gcd(ll a,ll b){
return b == 0 ? a : gcd(b,a % b);}
ll qpow(ll a,ll b,ll mod){
a %= mod;ll ans = 1;while(b){
if(b & 1)ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;}
struct cmp2{
bool operator()(const pii & a, const pii & b){
return a.second < b.second;}};
int lb(int x){
return x & -x;}
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5+5;
int a[maxn];
std::vector<int> vv[maxn];
int vis[maxn];
int id[maxn];
int fa[maxn];
int findx(int x)
{
return x == fa[x] ? x : fa[x] = findx(fa[x]);
}
bool cmp(int x,int y)
{
return a[x] > a[y];
}
int per[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T -- )
{
int n,m;
scanf("%d%d",&n,&m);
for (int i =1 ; i <= n; i ++ )
{
vis[i] = 0;
vv[i].clear();
per[i] = 0;
}
for (int i =1 ; i <= n; i ++ )
scanf("%d",&a[i]);
for (int i =1; i <= m; i ++ )
{
int x,y;
scanf("%d%d",&x,&y);
vv[x].pb(y);
vv[y].pb(x);
}
for (int i = 1; i <= n; i ++ )
{
fa[i] = i;
id[i] = i;
}
sort(id + 1,id + 1 + n,cmp);
for (int i = 1; i <= n; i ++ )
{
int x = id[i];
vis[x] = 1;
for (int j = 0; j < vv[x].size(); j ++ )
{
int v = vv[x][j];
if(vis[v] == 1)
{
int yy = findx(v);
if(yy != x)
{
fa[yy] = x;
per[yy] = x;
}
}
}
}
ll ans = 0;
for(int i = 1; i <= n; i ++ )
{
ans += a[i] - a[per[i]];
}
cout<<ans<<endl;
}
}