2018百度之星资格赛 三原色图

两次Kruskal,记录最小的、输出,然后每多一条边(不同方案加的边不一定相同,有点坑),分别加在两个答案上,比较最小的输出。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 102;
const int M = 102;
int f[N];
struct Edge
{
    int st,to,val;
    char c[2];
    bool flag1,flag2;
    bool operator <(const Edge &t)const{
        return val<t.val;
    }
}edge[M];
void Init(int n)
{
    for(int i = 1; i<=n; i++) f[i]=i;
}
int Find(int x)
{
    if(x!=f[x]) f[x] = Find(f[x]);
    return f[x];
}
bool Un(int x,int y)
{
    x= Find(x); y = Find(y);
    if(x!=y){
        f[x] = y;
        return 1;
    }
    return 0;
}
int Kruskal1(int n,int m)
{
    int ans = 0,cnt = 0;
    //sort(edge+1,edge+m+1);
    for(int i = 1; i<=m; i++){
        if(edge[i].c[0]!='B'&&Un(edge[i].st,edge[i].to)){
            ans+=edge[i].val; edge[i].flag1=true;
            cnt++; 
        } //printf("cnt %d\n",cnt);
    }
    if(cnt!=n-1) return inf;
    return ans;
}
int Kruskal2(int n,int m)
{
    int ans = 0,cnt = 0;
    //sort(edge+1,edge+m+1);
    for(int i = 1; i<=m; i++){
        if(edge[i].c[0]!='R'&&Un(edge[i].st,edge[i].to)){
            ans+=edge[i].val;
            cnt++;  edge[i].flag2=true;
        } //printf("cnt %d\n",cnt);
    }
    if(cnt!=n-1) return inf;
    return ans;
}
int main()
{
    int t,n,m; 
    scanf("%d",&t);
    for(int cas = 1; cas<=t; cas++)
    {
        memset(edge,0,sizeof(edge));
        scanf("%d%d",&n,&m);
        for(int i = 1; i<=m; i++){
            scanf("%d%d%d%s",&edge[i].st,&edge[i].to,&edge[i].val,edge[i].c);
        }
        //for(int i = 1; i<=m; i++) printf("%d%d%d%s\n",edge[i].st,edge[i].to,edge[i].val,edge[i].c);
        Init(n);
        sort(edge+1,edge+m+1);
        int ans1=Kruskal1(n,m);
    //    printf("%d\n",ans1);
        Init(n); 
        int ans2=Kruskal2(n,m);
    //    printf("%d\n",ans2);
        printf("Case #%d:\n",cas);
        for(int i = 1; i<n-1; i++){
            printf("-1\n");
        }
        if(ans1!=inf||ans2!=inf){
//            if(ans1<ans2) {
                printf("%d\n",min(ans1,ans2));
                for(int i = n; i<=m; i++){
                    for(int k = 1; k<=m; k++){
                        if(!edge[k].flag1) { 
                            ans1+=edge[k].val;
                            //printf("%d\n",ans1);
                            edge[k].flag1=true;
                            break;}
                    }
                    
                    for(int k = 1; k<=m; k++){
                        if(!edge[k].flag2) {
                            ans2+=edge[k].val;
                            //printf("%d\n",ans2);
                            edge[k].flag2=true;
                            break;}
                    }
                printf("%d\n",min(ans1,ans2));
                }
//            }
//            else{
//                printf("%d\n",ans2);
//                for(int i = n; i<=m; i++){
//                    for(int k = 1; k<=m; k++){
//                        if(!edge[k].flag2) {
//                            ans2+=edge[k].val;
//                            printf("%d\n",ans2);
//                            edge[k].flag2=true;
//                            break;}
//                    }
//                }
//            }
        }
        else{
            for(int i = n-1; i<=m; i++)
                printf("-1\n");
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值