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;
    }
  • 相关阅读:
    训练总结
    图论--最短路--SPFA模板(能过题,真没错的模板)
    图论--最短路-- Dijkstra模板(目前见到的最好用的)
    The 2019 Asia Nanchang First Round Online Programming Contest B Fire-Fighting Hero(阅读理解)
    关于RMQ问题的四种解法
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 K题 center
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 XKC's basketball team
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 D Carneginon
    ZOJ 3607 Lazier Salesgirl (枚举)
    ZOJ 3605 Find the Marble(dp)
  • 原文地址:https://www.cnblogs.com/huangzzz/p/9437671.html
Copyright © 2011-2022 走看看