首页 > 其他 > 详细

《HDU 2020 多校第二场》

时间:2020-07-24 10:24:50      阅读:65      评论:0      收藏:0      [点我收藏+]

Total Eclipse

思路:先考虑一种普遍解法。

对于每个极大连通块,一次次块上的全部点减去1,断开为子图后继续重复减1,显然是最优的减法。

但是减去后遍历边的复杂度过高,且b值也很大,所以考虑成加边的形式。

首先将点按权值降序。那么我们可以采取将最大的点减成第二大的点,然后两个点又一起减成第三大的点,然后三个点一起减成第四大.....

那么显然这中间能不能一起减去这个代价会是分界,当两个点可以从之前的点间接相连,或者他们可以直接相连时,那么显然可以一起减,

因为之前的点显然和他们已经减到了相同代价。如果不能直接或者间接相连,那么就是两个不同的连通块里的点,那么就要*连通块的个数。

那么每一次的代价就是 num(连通块) * (b[i] - b[i+1]).

所以,我们用并查集来维护连通块的个数,每次计算一个点时,先将这个点合并到和它相连的点且之前出现过的点的连通块中。

Code:

技术分享图片
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e5+5;
const LL Mod = 1e9+9;
#define pi acos(-1)
#define INF 1e8
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read()
{
     int x = 0,f = 1;char c = getchar();
     while(c < 0 || c > 9){if(c == -) f = -1;c = getchar();}
     while(c >= 0 && c <= 9){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
     return x*f;
}
struct Node{
     int val,id;
     bool operator < (const Node &a)const{
          return val > a.val;
     }
}p[N];
int vis[N],fa[N];
vector<int> G[N];
int Find(int x)
{
     return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
int main()
{
     freopen("data1.in","r",stdin);
     freopen("data1.out","w",stdout);
     int t;t = read();
     while(t--)
     {
          int n,m;
          n = read(),m = read();
          for(int i = 1;i <= n;++i) 
          {
               p[i].val = read();
               p[i].id = fa[i] = i;
               G[i].clear();
               vis[i] = 0;
          }
          sort(p+1,p+n+1);
          p[n+1].val = 0;
          while(m--)
          {
               int u,v;
               u = read(),v = read();
               G[u].push_back(v);
               G[v].push_back(u);
          }
          LL ans = 0;
          int cnt = 0;//连通块数量
          for(int i = 1;i <= n;++i)
          {
               int x = p[i].id;
               vis[x] = 1;
               cnt++;
               for(auto v : G[x])
               {
                    if(!vis[v]) continue;
                    int xx = Find(x),yy = Find(v);
                    if(xx != yy)
                    {
                         fa[xx] = yy;
                         cnt--;
                    }
               }
               ans += 1LL*(p[i].val-p[i+1].val)*cnt;
          }
          printf("%lld\n",ans);
     }
     system("pause");
     return 0;
}
View Code

 

《HDU 2020 多校第二场》

原文:https://www.cnblogs.com/zwjzwj/p/13370013.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!