日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【杭电多校2020】Total Eclipse【贪心】【并查集】

發布時間:2023/12/3 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【杭电多校2020】Total Eclipse【贪心】【并查集】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意:nnn個點mmm條邊的無向圖,每個點有一個正點權,每次選擇一個連通子圖,將里面的權值都減111。求所有點權為000的最小步數。

T≤10,n≤105,m≤2×105T\leq 10,n\leq 10^5,m\leq2\times10^5T10,n105,m2×105

考慮一個貪心:每次一定選擇一個極大的連通塊。

感性理解很容易,還是證明一下:

假設一個極大連通塊SSS,我偏不選,選擇它的子連通塊來覆蓋整個SSS,答案嚴格更優。考慮兩個連在一起的連通塊T1,T2T_1,T_2T1?,T2?,選擇T1∪T2,T1∩T2T_1\cup T_2,T_1\cap T_2T1?T2?,T1?T2?一定不比選T1,T2T_1,T_2T1?,T2?劣。因為選擇的連通塊覆蓋了整個SSS,所以可以一步步合并出SSS(即任選一個與當前集合相鄰的點,將覆蓋它的集合與當前集合合并),答案不會更劣,矛盾。

對于一個連通塊來說,一定是點按照權值從小到大被刪。把操作順序倒過來,就是把大的結點減小成和小的結點相同,然后一起刪掉。

形式化地講,就是把權值從大到小排序依次加入,并把全場的權值都減到當前權值。用并查集維護連通塊個數即可。

復雜度O(nlog?n)O(n\log n)O(nlogn)

#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <algorithm> #include <vector> #define MAXN 100005 using namespace std; typedef long long ll; vector<int> e[MAXN]; int fa[MAXN]; inline int find(const int& x){return fa[x]==x? x:fa[x]=find(fa[x]);} int a[MAXN],p[MAXN],vis[MAXN]; inline bool cmp(const int& x,const int& y){return a[x]>a[y];} int main() {int T;scanf("%d",&T);while (T--){int n,m;scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) e[i].clear(),fa[i]=p[i]=i,vis[i]=0,scanf("%d",&a[i]);for (int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);e[u].push_back(v),e[v].push_back(u);}sort(p+1,p+n+1,cmp);int cur=1;ll ans=0;vis[p[1]]=1;for (int i=2;i<=n;i++){ans+=(ll)cur*(a[p[i-1]]-a[p[i]]);++cur;for (vector<int>::iterator it=e[p[i]].begin();it!=e[p[i]].end();++it){int u=p[i],v=*it;if (!vis[v]) continue;u=find(u),v=find(v);if (u!=v) fa[u]=v,--cur;}vis[p[i]]=1;}ans+=(ll)cur*a[p[n]];printf("%lld\n",ans);}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的【杭电多校2020】Total Eclipse【贪心】【并查集】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。