题目大意:
1、n个点,m-1条边,每条边有两个权值,权1表示用高价修路,权2表示用低价修路。
2、求:选k条高价路的情况下,最小生成树的边权最大值是多少?
解题思路:
1、题目框架和昨天做的2654tree似乎一样,都是双色道路,其中一个颜色选特定的数量。
2、但认真看题发现,这题要水一些。题目已经规定,高价的道路一定比低价的道路贵,就不用担心交叉权值的问题。
3、所以,直接跑两次最小生成树就完事了!赤裸裸的模板
上代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int mx=20005;
int n,m,k,ans=0;
struct nodb{int x,y,s1,s2,gg,v;}e[mx],b[mx];
int la[mx],f[mx];
bool cmp1(nodb x, nodb y) { return x.s1<y.s1; }
bool cmp2(nodb x, nodb y) { return x.s2<y.s2; }
int ch(int x) { if(x==f[x]) return x; return f[x]=ch(f[x]); }
void bk()
{ int kk=0;
sort(e+1,e+1+m,cmp1);
for(int i=1;i<=m;i++)
{
if(e[i].v==1)
{
int xx=ch(e[i].x);
int yy=ch(e[i].y);
if(xx!=yy)
{
f[xx]=yy;
e[i].v=0;//选这条边
if(ans<e[i].s1) ans=e[i].s1;//取极值
kk++; if(kk==k) break;
}
}
}
}
void bn()
{
int kk=0;
sort(e+1,e+1+m,cmp2);
for(int i=1;i<=m;i++)
{
if(e[i].v==1)
{
int xx=ch(e[i].x);
int yy=ch(e[i].y);
if(xx!=yy)
{
f[xx]=yy;
e[i].v=0;//选这条边
if(ans<e[i].s2) ans=e[i].s2;//取极值
kk++; if(kk==n-1-k) break;
}
}
}
}
int main()
{
scanf("%d %d %d",&n,&k,&m);
for(int i=1;i<m;i++)
{
scanf("%d %d %d %d",&e[i].x,&e[i].y,&e[i].s1,&e[i].s2);
e[i].v=1;
}
for(int i=1;i<=n;i++) { la[i]=0;f[i]=i; }
bk();//先取高价的k条路
bn();//再取余下的路
printf("%d\n",ans);
return 0;
}