​2018”百度之星”程序设计大赛 - 资格赛 三原色图 problem 1006​​​
题意:k条边可以找到只有红绿边构成的最小生成树,或者只有蓝绿构成的最小生成树。
思路:输出m行,前n-1行都是-1不可能构成最小生成树,然后分别找由蓝绿和红绿构成的最小生成树,然后慢慢加最小的边,留下小的,krusral。
emmmm资格赛过一题就好了,所以看了这题有了思路就没写了。后来敲的时候有点问题。嗯下面贴上AC代码,这些题在上可以继续交的。

//n-m 100 w 1000
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxm=2*100+10;
const int maxn=100+10;
int n,m;
int f[maxn],tot;
bool vis[maxn][maxn],vis1[maxn][maxn];
int Ans[maxm];
struct node{
int from;
int to,v,flag;
int e;//0 1 2
bool operator <(const node &u)const{
return v<u.v;
}
}edge[maxm];
void add(int a,int b,int v,char c){
edge[tot].from=a;edge[tot].to=b;edge[tot].e=c;
edge[tot++].v=v;
}
int find(int x){
return f[x]==-1?x:f[x]=find(f[x]);
}
void kruskal(int nu)
{
memset(f,-1,sizeof(f));
for(int i=0;i<tot;++i) edge[i].flag=0;
sort(edge,edge+tot);
int cnt=0,ans=0;
for(int i=0;cnt<n-1&&i<tot;++i){
if(edge[i].e==nu) continue;
int fu=find(edge[i].from),fv=find(edge[i].to);
if(fu!=fv){
edge[i].flag=1;
cnt++;
ans+=edge[i].v;
f[fv]=fu;
}
}

if(cnt!=n-1) return;
if(Ans[cnt]==-1) Ans[cnt]=ans;
else Ans[cnt]=min(Ans[cnt],ans);
for(int i=0;i<tot;++i){
if(edge[i].flag) continue;
cnt++;
ans+=edge[i].v;
if(Ans[cnt]==-1) Ans[cnt]=ans;
else Ans[cnt]=min(Ans[cnt],ans);
}
}

int main()
{
int T,kcase=1;
int a,b,c;
char d;
int ch;
scanf("%d",&T);
while(T--)
{
tot=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d %d %d %c",&a,&b,&c,&d);

if(d=='R') ch=0;
else if(d=='G') ch=1;
else if(d=='B') ch=2;
add(a,b,c,ch);
}
memset(Ans,-1,sizeof(Ans));
kruskal(0);//
kruskal(2);
printf("Case #%d:\n",kcase++);
for(int i=1;i<=m;++i) printf("%d\n",Ans[i]);
}
return 0;
}