正题
题目大意
一张无向图,求剩下一些边使图联通且wG∗max{gVi}+wS∗max{sVi}wG*max\{g_{V_i}\}+wS*max\{s_{V_i}\}wG∗max{gVi}+wS∗max{sVi}最小
VVV表示选的边集
解题思路
我们可以枚举max{si}max\{s_i\}max{si}的值,然后用ggg跑最小生成树。时间复杂度O(m2)O(m^2)O(m2),就可以成功TLETLETLE
这时,就需要用到最小生成树的性质。对于新的一个max{si}max\{s_i\}max{si},你只能加入一条新的边,直接用这个加进去跑一边最小生成树就好了。
codecodecode
#include<cstdio>
#include<algorithm>
#define Inf 1e18
#define N 500
#define M 50010
#define ll long long
using namespace std;
struct node{ll x,y,g,s;
}a[M];
ll n,m,wS,wG,ans,tot;
ll fa[N],s[M],p[N];
bool cmp(node x,node y)
{return x.g<y.g;}
ll find(ll x)
{return fa[x]==x?x:fa[x]=find(fa[x]);}
void unionn(ll x,ll y)
{ll Fa=find(x),Fb=find(y);if(Fa<Fb) fa[Fb]=Fa;else fa[Fa]=Fb;
}
int main()
{scanf("%lld%lld%lld%lld",&n,&m,&wG,&wS);for(ll i=1;i<=m;i++){scanf("%lld%lld%lld%lld",&a[i].x,&a[i].y,&a[i].g,&a[i].s);}ans=Inf;sort(a+1,a+1+m,cmp);for(ll i=1;i<=m;i++){if(a[i].x==a[i].y)continue;ll j,k=0,cnt=0;for(j=1;j<=n;j++)fa[j]=j;for(j=tot;j>=1;j--)if(a[p[j]].s>a[i].s) p[j+1]=p[j];else break;p[j+1]=i;tot++;for(j=1;j<=tot;j++){if(find(a[p[j]].x)!=find(a[p[j]].y)){unionn(a[p[j]].x,a[p[j]].y);k=max(k,a[p[j]].s);p[++cnt]=p[j];}if(cnt==n-1) break;}if(cnt==n-1) ans=min(ans,k*wS+a[i].g*wG);tot=cnt;}if(ans==Inf) printf("-1");else printf("%lld",ans);
}