2018 百度之星 初赛 第六题
Posted stranger-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018 百度之星 初赛 第六题相关的知识,希望对你有一定的参考价值。
三原色图
度度熊有一张 nn 个点 mm 条边的无向图,所有点按照 1,2,cdots,n1,2,?,n 标号,每条边有一个正整数权值以及一种色光三原色红、绿、蓝之一的颜色。
现在度度熊想选出恰好 kk 条边,满足只用这 kk 条边之中的红色边和绿色边就能使 nn 个点之间两两连通,或者只用这 kk 条边之中的蓝色边和绿色边就能使 nn 个点之间两两连通,这里两个点连通是指从一个点出发沿着边可以走到另一个点。
对于每个 k=1,2,cdots,mk=1,2,?,m,你都需要帮度度熊计算选出恰好 kk 条满足条件的边的权值之和的最小值。
第一行包含一个正整数 TT,表示有 TT 组测试数据。
接下来依次描述 TT 组测试数据。对于每组测试数据:
第一行包含两个整数 nn 和 mm,表示图的点数和边数。
接下来 mm 行,每行包含三个整数 a,b,wa,b,w 和一个字符 cc,表示有一条连接点 aa 与点 bb 的权值为 ww、颜色为 cc 的无向边。
保证 1 leq T leq 1001≤T≤100,1 leq n,m leq 1001≤n,m≤100,1 leq a,b leq n1≤a,b≤n,1 leq w leq 10001≤w≤1000,c in {R,G,B}c∈{R,G,B},这里 R,G,BR,G,B 分别表示红色、绿色和蓝色。
对于每组测试数据,先输出一行信息 "Case #x:"(不含引号),其中 x 表示这是第 xx 组测试数据,接下来 mm 行,每行包含一个整数,第 ii 行的整数表示选出恰好 ii 条满足条件的边的权值之和的最小值,如果不存在合法方案,输出 -1?1,行末不要有多余空格。
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
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 }
以上是关于2018 百度之星 初赛 第六题的主要内容,如果未能解决你的问题,请参考以下文章