题目描述
思路:
拿到题的时候没太看懂了题意,搞了半小时
其实就是运用贪心思想——先将各个边按g的大小排序这样在后面处理时就可以不考虑g了
再来处理s,对于s,我们每一次只新增一条边,在如果处理边的s小于队列中最大s,则可利用插入排序原理将此边加入边的队列,并且每一次处理完之后都生成一次最小生成树,如果最小生成树的边==n-1的花就进行一次ans的赋值
注意:1.队列中边数最大值只能等于n-1,所以每一次完成一次生成树之后,top=使用的边数
2. 对于每一次使用的边,将其队列位置更新(因为之前未使用的边之后也不可能比此时情况更优
完结撒花:)
Code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+10;
struct node{
ll x,y,g,s;
}e[N];
ll n,m,fa[N],top,p[N];
ll wwg,wws;
int find(int x){
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
bool cmp(node a,node b){
return a.g<b.g;
}
int main(){
ll ans=1e18;
scanf("%lld%lld%lld%lld",&n,&m,&wwg,&wws);
for(ll i=1;i<=m;i++){
scanf("%lld%lld%lld%lld",&e[i].x,&e[i].y,&e[i].g,&e[i].s);
}
sort(e+1,e+1+m,cmp);
for(ll i=1;i<=m;i++){
for(ll k=1;k<=n;k++) fa[k]=k;
ll j;
for(j=top;j>=1;j--){
if(e[p[j]].s>e[i].s){
p[j+1]=p[j];
}
else break;
}
top++;
p[j+1]=i;
ll maxg=0,maxs=0,sum=0;
for(int k=1;k<=top;k++){
ll xx=find(e[p[k]].x),yy=find(e[p[k]].y);
if(xx!=yy){
fa[xx]=yy;
maxg=max(e[p[k]].g, maxg);
maxs=max(e[p[k]].s, maxs);
p[++sum]=p[k];
}
}
if(sum==n-1)
ans=min(ans, wwg*maxg+wws*maxs);
top=sum;//不要忘了
}
if(ans==1e18) puts("-1");
else printf("%lld",ans);
return 0;
}