题意:传送门
题解:因为要满足至少做k条高速的,所以可以先将所有高速公路krusal一下,之后把没用到的高速路加到普通路上,因为害怕普通路比高速路花费还要更大,然后把剩下的高速路和普通路再次krusal一下,中间导导答案就可以了。
附上代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
const int maxm=(2e4+5)*2;
struct edge{
int u,v,w,next;
bool used;
};
edge edges1[maxm],edges2[maxm];
int head1[maxn],tot1,head2[maxn],tot2;
bool cmp(edge a,edge b)
{
return a.w<b.w;
}
int n,k,m,ans;
void init1()
{
memset(head1,-1,sizeof(head1));
tot1=0;
}
void init2()
{
memset(head2,-1,sizeof(head2));
tot2=0;
}
void add_edges1(int u,int v,int w)
{
edges1[tot1].u=u;
edges1[tot1].v=v;
edges1[tot1].w=w;
edges1[tot1].used=false;
edges1[tot1].next=head1[u];
head1[u]=tot1++;
}
void add_edges2(int u,int v,int w)
{
edges2[tot2].u=u;
edges2[tot2].v=v;
edges2[tot2].w=w;
edges2[tot2].next=head2[u];
head2[u]=tot2++;
}
int f[maxn];
int find(int x)
{
if(x==f[x]){
return x;
}else{
return f[x]=find(f[x]);
}
}
void merge(int a,int b)
{
int x1=find(a),y1=find(b);
if(x1!=y1){
f[y1]=x1;
}
}
void krusal1()
{
for(int i=1;i<=n;i++){
f[i]=i;
}int cnt=0;
for(int i=0;i<tot1;i++){
edge &u=edges1[i];
int a=find(u.u),b=find(u.v);
if(a!=b){
cnt++;
// cout<<a<<" "<<b<<endl;
u.used=true;
merge(a,b);
ans=max(ans,u.w);
}
if(cnt==k){
return ;
}
}
}
void krusal2()
{
for(int i=0;i<tot2;i++){
edge &u=edges2[i];
int a=find(u.u),b=find(u.v);
int cnt=0;
if(a!=b){
cnt++;
merge(a,b);
ans=max(ans,u.w);
}
}
}
int main()
{
init1();init2();
scanf("%d%d%d",&n,&k,&m);
for(int i=1;i<m;i++){
int a,b,c1,c2;
scanf("%d%d%d%d",&a,&b,&c1,&c2);
add_edges1(a,b,c1);
add_edges2(a,b,c2);
}
sort(edges1,edges1+tot1,cmp);
krusal1();
for(int i=0;i<tot1;i++){
if(!edges1[i].used){
edge &u=edges1[i];
add_edges2(u.u,u.v,u.w);
}
}
sort(edges2,edges2+tot2,cmp);
krusal2();
printf("%d\n",ans);
return 0;
}
第二种做法:直接二分答案
附上代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
int n,K,m,ans;
int fa[10005];
struct data{int x,y,c1,c2;}e[20005];
int find(int x)
{return x==fa[x]?x:fa[x]=find(fa[x]);}
bool jud(int x)
{
for(int i=1;i<=n;i++)fa[i]=i;
int cnt=0;
for(int i=1;i<=m;i++)
{
if(e[i].c1>x)continue;
int p=find(e[i].x),q=find(e[i].y);
if(p!=q)
{fa[p]=q;cnt++;}
}
if(cnt<K)return 0;
for(int i=1;i<=m;i++)
{
if(e[i].c2>x)continue;
int p=find(e[i].x),q=find(e[i].y);
if(p!=q)
{fa[p]=q;cnt++;}
}
if(cnt!=n-1)return 0;
return 1;
}
int main()
{
n=read(),K=read(),m=read();
for(int i=1;i<m;i++)
e[i].x=read(),e[i].y=read(),e[i].c1=read(),e[i].c2=read();
int l=0,r=30001;
while(r-l>1)
{
int mid=(l+r)>>1;
if(jud(mid)){r=mid;}
else {l=mid;}
}
printf("%d",r);
return 0;
}