• 2018 百度之星 初赛 第六题 HDU6349


    三原色图

     
     Accepts: 281
     
     Submissions: 1261
     Time Limit: 1500/1000 MS (Java/Others)
     
     Memory Limit: 262144/262144 K (Java/Others)
    Problem Description

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

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

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

    Input

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

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

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

    接下来 mm 行,每行包含三个整数 a,b,wa,b,w 和一个字符 cc,表示有一条连接点 aa 与点 bb 的权值为 ww、颜色为 cc 的无向边。

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

    Output

    对于每组测试数据,先输出一行信息 "Case #x:"(不含引号),其中 x 表示这是第 xx 组测试数据,接下来 mm 行,每行包含一个整数,第 ii 行的整数表示选出恰好 ii 条满足条件的边的权值之和的最小值,如果不存在合法方案,输出 -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

    解析 直接建图 判断连不连通 跑最小生成树 特判1个点的情况。

    AC代码
      1 #include <bits/stdc++.h>
      2 #define pb push_back
      3 #define mp make_pair
      4 #define fi first
      5 #define se second
      6 #define all(a) (a).begin(), (a).end()
      7 #define fillchar(a, x) memset(a, x, sizeof(a))
      8 #define huan printf("
    ");
      9 #define debug(a,b) cout<<a<<" "<<b<<" "<<endl;
     10 using namespace std;
     11 typedef long long ll;
     12 const int maxn=150+10,inf=0x3f3f3f3f;
     13 const ll mod=1e9+7;
     14 int n,m;
     15 int p[maxn],par[maxn],g[maxn][maxn];
     16 struct edge
     17 {
     18     int u,v,w,id;
     19     char col;
     20 } a[maxn],b[maxn],c[maxn];
     21 int cmp(edge a,edge b)
     22 {
     23     return a.w<b.w;
     24 }
     25 int find_(int x)
     26 {
     27     return p[x]==x?x:p[x]=find_(p[x]);
     28 }
     29 int _find(int x)
     30 {
     31     return x==par[x]?x:par[x]=_find(par[x]);
     32 }
     33 void unio(int a,int b)
     34 {
     35     int ra=_find(a);
     36     int rb=_find(b);
     37     if(ra!=rb)
     38         par[rb]=ra;
     39 }
     40 int ans1[maxn],ans2[maxn];
     41 int main()
     42 {
     43     int t,kase=1;
     44     cin>>t;
     45     while(t--)
     46     {
     47         map<int,int> mp;
     48         scanf("%d %d",&n,&m);
     49         int u,v,w;
     50         for(int i=0; i<m; i++)
     51         {
     52             cin>>a[i].u>>a[i].v>>a[i].w>>a[i].col;
     53             a[i].id=i;
     54         }
     55         printf("Case #%d:
    ",kase++);
     56         sort(a,a+m,cmp);
     57         //for(int i=0;i<m;i++)
     58            // debug(a[i].w,a[i].col);
     59         if(n==1)
     60         {
     61             int sum=0;
     62             for(int i=0; i<m; i++)
     63             {
     64                 sum+=a[i].w;
     65                 cout<<sum<<endl;
     66             }
     67             continue;
     68         }
     69 //------------------------------------------------------------------------------
     70         int cnt=0,flag1=1;mp.clear();
     71         memset(g,inf,sizeof(g));
     72         memset(ans1,inf,sizeof(ans1));
     73         for(int i=1; i<=n; i++)
     74             p[i]=i,par[i]=i;
     75         for(int i=0; i<m; i++)
     76         {
     77             if((a[i].col=='R'||a[i].col=='G')&&a[i].w<g[a[i].u][a[i].v]&&a[i].u!=a[i].v)
     78             {
     79                 g[a[i].u][a[i].v]=g[a[i].v][a[i].u]=a[i].w;
     80                 b[cnt++]= {a[i].u,a[i].v,a[i].w,a[i].id,a[i].col};
     81                 unio(a[i].u,a[i].v);
     82             }
     83         }
     84         for(int i=2; i<=n; i++)
     85             if(_find(i-1)!=_find(i))flag1=0;
     86         if(flag1)
     87         {
     88             sort(b,b+cnt,cmp);
     89             ans1[n-1]=0;
     90             for(int i=0; i<cnt; i++)
     91             {
     92                 int x,y,z;
     93                 x=find_(b[i].u),y=find_(b[i].v),z=b[i].w;
     94                 if(x!=y)
     95                 {
     96                     ans1[n-1]+=z;
     97                     mp[b[i].id]=1;
     98                     p[x]=y;
     99                 }
    100             }
    101             int k=n;
    102             for(int i=0; i<m; i++)
    103             {
    104                 if(mp[a[i].id]==0)
    105                     ans1[k]=ans1[k-1]+a[i].w,k++;
    106             }
    107         }
    108 //---------------------------------------------------------------------------------------------
    109         int flag2=1;cnt=0;mp.clear();
    110         memset(g,inf,sizeof(g));
    111         memset(ans2,inf,sizeof(ans2));
    112         for(int i=1; i<=n; i++)
    113             p[i]=i,par[i]=i;
    114         for(int i=0; i<m; i++)
    115         {
    116             if((a[i].col=='B'||a[i].col=='G')&&a[i].w<g[a[i].u][a[i].v]&&a[i].u!=a[i].v)
    117             {
    118                 g[a[i].u][a[i].v]=g[a[i].v][a[i].u]=a[i].w;
    119                 b[cnt++]={a[i].u,a[i].v,a[i].w,a[i].id,a[i].col};
    120                 unio(a[i].u,a[i].v);
    121             }
    122         }
    123         for(int i=2; i<=n; i++)
    124             if(_find(i-1)!=_find(i))flag2=0;
    125         if(flag2==0&&flag1==0)
    126         {
    127             for(int i=1;i<=m; i++)
    128                 cout<<-1<<endl;
    129             continue;
    130         }
    131         if(flag2)
    132         {
    133 
    134             sort(b,b+cnt,cmp);
    135             ans2[n-1]=0;
    136             for(int i=0; i<cnt; i++)
    137             {
    138                 int x,y,z;
    139                 x=find_(b[i].u),y=find_(b[i].v),z=b[i].w;
    140                 if(x!=y)
    141                 {
    142                     ans2[n-1]+=z;
    143                     mp[b[i].id]=1;
    144                     p[x]=y;
    145                 }
    146             }
    147             int k=n;
    148             for(int i=0; i<m; i++)
    149             {
    150                 if(mp[a[i].id]==0)
    151                     ans2[k]=ans2[k-1]+a[i].w,k++;
    152             }
    153         }
    154         for(int i=1; i<n-1; i++)
    155             cout<<-1<<endl;
    156         for(int i=n-1; i<=m; i++)
    157         {
    158             cout<<min(ans1[i],ans2[i])<<endl;
    159         }
    160     }
    161 }
    View Code
  • 相关阅读:
    彻底卸载Win11小组件
    pydantic学习与使用9.枚举类型(enum) 上海
    FastAPI学习1.环境准备与基础入门 上海
    python asyncio 异步 I/O 协程(Coroutine)与运行 上海
    pydantic学习与使用10.日期时间类型(datetime) 上海
    pydantic学习与使用12.使用 Field 定制字段 上海
    pydantic学习与使用11.pycharm插件pydantic 语法提示功能 上海
    pydantic学习与使用8.requiredfields必填字段省略号( ...) 上海
    python笔记72 使用pathlib替代os.path 上海
    python asyncio 异步 I/O 实现并发http请求(asyncio + aiohttp) 上海
  • 原文地址:https://www.cnblogs.com/stranger-/p/9420169.html
Copyright © 2020-2023  润新知