http://acm.hdu.edu.cn/showproblem.php?pid=6763
和claris心意相通了,默认取最大了。。。
从大到小对点值排序,然后依次加入,考虑u周围的连通块有多少,因为他们都比a[u]大,且他们最后连,就可以减去(d-1)*a[u],旁边没有点已经入队就相当于答案加上a[u]
整个思路有点像最小生成树
#include<bits/stdc++.h>
using namespace std;
struct Node{
int id,val;
bool operator<(const Node &b)const{
if(val==b.val)return id<b.id;
return val<b.val;
}
}a[100010];
int vis[100010],f[100010];
vector<int>e[100010];
inline int find(int x)
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].val);
a[i].id=i;
e[i].clear();
vis[i]=0;
}
for(int i=0;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
sort(e[i].begin(),e[i].end());
e[i].erase(unique(e[i].begin(),e[i].end()),e[i].end());
f[i]=i;
}
priority_queue<Node>q;
vector<int> tmp;
for(int i=1;i<=n;i++)q.push(a[i]);
long long ans=0;int xx,yy;
while(!q.empty()){
Node t=q.top();q.pop();
vis[t.id]=1;tmp.clear();
long long d=0;
for(int i=0;i<e[t.id].size();i++){
if(vis[e[t.id][i]])
tmp.push_back(find(e[t.id][i]));
}
sort(tmp.begin(),tmp.end());
tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());
d=tmp.size();
ans-=(d-1)*t.val;
for(int x:tmp)
{
xx=find(x);
yy=find(t.id);
if(xx!=yy)
f[yy]=xx;
}
}
printf("%lld\n",ans);
}
}