zoukankan      html  css  js  c++  java
  • 2018 百度之星 1006 最小生成树

    http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=820&pid=1006

    度度熊有一张 nnn 个点 mmm 条边的无向图,所有点按照 1,2,⋯,n1,2,cdots,n1,2,,n 标号,每条边有一个正整数权值以及一种色光三原色红、绿、蓝之一的颜色。

    现在度度熊想选出恰好 kkk 条边,满足只用这 kkk 条边之中的红色边和绿色边就能使 nnn 个点之间两两连通,或者只用这 kkk 条边之中的蓝色边和绿色边就能使 nnn 个点之间两两连通,这里两个点连通是指从一个点出发沿着边可以走到另一个点。

    对于每个 k=1,2,⋯,mk=1,2,cdots,mk=1,2,,m,你都需要帮度度熊计算选出恰好 kkk 条满足条件的边的权值之和的最小值。

    Input

    第一行包含一个正整数 TTT,表示有 TTT 组测试数据。

    接下来依次描述 TTT 组测试数据。对于每组测试数据:

    第一行包含两个整数 nnn 和 mmm,表示图的点数和边数。

    接下来 mmm 行,每行包含三个整数 a,b,wa,b,wa,b,w 和一个字符 ccc,表示有一条连接点 aaa 与点 bbb 的权值为 www、颜色为 ccc 的无向边。

    保证 1≤T≤1001 leq T leq 1001T100,1≤n,m≤1001 leq n,m leq 1001n,m100,1≤a,b≤n1 leq a,b leq n1a,bn,1≤w≤10001 leq w leq 10001w1000,c∈{R,G,B}c in {R,G,B}c{R,G,B},这里 R,G,BR,G,BR,G,B 分别表示红色、绿色和蓝色。

    Output

    对于每组测试数据,先输出一行信息 "Case #x:"(不含引号),其中 x 表示这是第 xxx 组测试数据,接下来 mmm 行,每行包含一个整数,第 iii 行的整数表示选出恰好 iii 条满足条件的边的权值之和的最小值,如果不存在合法方案,输出 −1-11,行末不要有多余空格。

    Sample Input
    1
    5 8
    1 5 1 R
    2 1 2 R
    5 4 5 R
    4 5 3 G
    1 3 3 G
    4 3 5 G
    5 4 1 B
    1 2 2 B
    
    Sample Output
    Case #1:
    -1
    -1
    -1
    9
    10
    12
    17
    22
    



    题意:中文题不解释

    思路:建立两个图(红绿和蓝绿)开始求各自最小生成树 小于n-1条边输出-1(因为无法全部遍历) 等于n-1输出两个图跑最小生成树的最小值 大于n-1输出两个图分别跑最小生成树后剩下的边从小到大加
    进最小生成树的边然后还是要比较输出两个图的最小值(这个点没考虑到导致wa了n遍,,,说多了都是泪

    代码(很多不必要的操作,但是只是为了AC):
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<algorithm>
    #include<map>
    #define maxn 50010
    using namespace std;
    int par[maxn];
    int ranke[maxn];
    int vis[maxn],vis2[maxn];
    int used1[maxn],used2[maxn];
    int op1[maxn],op2[maxn];
    void init(int n)
    {
        for(int i=0;i<n;i++){
            par[i]=i;
            ranke[i]=0;
        }
    
    
    }
    int find(int x)//找父亲
    {
        if(par[x]==x)return x;
        else {
            return par[x]=find(par[x]);//递归找父亲(因为父亲是统一的)
        }
    }
    void unite(int x,int y)
    {
        x=find(x);
        y=find(y);
        if(x==y)return ;
        if(ranke[x]<ranke[y])
        {
            par[x]=y;
        }
        else par[y]=x;
        if(ranke[x]==ranke[y])ranke[x]++;
    }
    bool same(int x,int y)
    {
        return find(x)==find(y);
    }
    
    
    struct edge{
      int from,to,cost;
    };
    bool comp(const edge& e1,const edge& e2)
    {
        return e1.cost<e2.cost;
    }
    edge mp[maxn],mp2[maxn];
    int V,E,k1,k2;
    int res,res2;
    int flag,flag2;
    char col,cha;
    int kruskal()
    {
        flag=1;
          memset(used1,0,sizeof(used1));
        sort(mp,mp+k1,comp);
        init(V);
        res=0;
        for(int i=0;i<k1;i++)
        {
            edge s=mp[i];
            //cout<<s.from<<s.to<<endl;
            if(!same(s.from,s.to)){
                unite(s.from,s.to);
             flag++;
            res+=s.cost;
             used1[s.cost]++;
            }
        }
        return res;
    }
    int kruskal2()
    {
        flag2=1;
        memset(used2,0,sizeof(used2));
        sort(mp2,mp2+k2,comp);
        init(V);
        res2=0;
        for(int i=0;i<k2;i++)
        {
            edge s=mp2[i];
            if(!same(s.from,s.to)){
                unite(s.from,s.to);
            flag2++;
            res2+=s.cost;
            used2[s.cost]++;
            }
        }
        return res2;
    }
    int main()
    {
        int t;
        cin>>t;
        for(int z=1;z<=t;z++){
        int d1,d2,dis;
        int mon;
          cin>>V>>E;
           k1=0;
           k2=0;
           for(int i=0,j=0,jj=0;i<E;i++)
           {
               cin>>d1>>d2>>dis;
               scanf("%c%c",&cha,&col);
               vis[j++]=dis;
               vis2[jj++]=dis;
               d1--;
               d2--;
                if(col=='G'||col=='B')
               {
                  mp2[k2].from=d1;
                  mp2[k2].to=d2;
                  mp2[k2].cost=dis;
                  k2++;
               }
               if(col=='G'||col=='R'){
                mp[k1].from=d1;
                mp[k1].to=d2;
                mp[k1].cost=dis;
                k1++;
               }
           }
           //cout<<k2<<endl;
           cout<<"Case #"<<z<<":"<<endl;
           if(V==1){
            sort(vis,vis+E);
            int sum=0;
           for(int i=0;i<E;i++)
           {
               sum+=vis[i];
               cout<<sum<<endl;
           }
           }
           else {
           int ans1=kruskal();
            int ans2=kruskal2();
            //cout<<ans1<<endl;
            //cout<<flag2<<endl;
            int oo=0;
            if(flag!=V&&flag2!=V)
            {
                for(int i=0;i<E;i++){cout<<"-1"<<endl;oo=1;}
            }
            else if(flag!=V)  ans1=1000000000;
            else if(flag2!=V) ans2=1000000000;
            int num=0;
            if(oo==1)continue;
            for(int x=0;x<V-1-1;x++){
                op1[x]=-1;
                op2[x]=-1;
            }
           op1[V-2]=ans1;
           op2[V-2]=ans2;
              sort(vis,vis+E);
              for(int i=0;i<E;i++)
                {
                   if(used1[vis[i]]!=0){used1[vis[i]]--;vis[i]=1000000000;}
                }
               sort(vis,vis+E);
              int m=0;
              for(int ss=V-1;ss<E;ss++)
              {
                       op1[ss]=op1[ss-1]+vis[m++];
              }
                sort(vis2,vis2+E);
                for(int i=0;i<E;i++)
                {
                   // cout<<used2[vis[i]];
                   if(used2[vis2[i]]!=0){used2[vis2[i]]--;vis2[i]=1000000;}
                }
               sort(vis2,vis2+E);
              // for(int i=0;i<E;i++)cout<<vis[i]<<endl;
               m=0;
              for(int ss=V-1;ss<E;ss++)
              {
                  op2[ss]=op2[ss-1]+vis2[m++];
              }
            for(int i=0;i<E;i++)
            cout<<min(op1[i],op2[i])<<endl;
           }
    //        if(flag!=V)cout<<"No"<<endl;
    //       else
    //       {
    //           if(res>mon)cout<<"No"<<endl;
    //           else cout<<"Yes"<<endl;
    //       }
        }
        return 0;
    }
  • 相关阅读:
    14. Longest Common Prefix
    7. Reverse Integer
    用例图是软件项目成本预估的好帮手
    设计模式之创建性模式
    代码的核心定义文件
    一个项目经理的经验总结
    设计模式之结构型模式
    互联网发展十几年,你错过了哪些创业机会
    产品经理必读:像怀胎一样怀产品,要厚着脸皮听批评
    陌陌估值1亿美元:一个用户10美元,贵吗?
  • 原文地址:https://www.cnblogs.com/huangzzz/p/9437671.html
Copyright © 2011-2022 走看看