ac代码:
#include<bits/stdc++.h> #define per(i,a,b) for(int i=a;i<=b;i++) using namespace std; typedef long long ll; const int mod=998244353; const int inf =0x3f3f3f3f; const double eps=1e-8; #define siz 110 int n,m,Enum,ans[siz]; struct Edge { int a,b,w; int ch;//红0 绿1 蓝2 bool vis; bool operator<(Edge&e){return w<e.w;} }edge[siz],tmp; int f[siz];//点 vector<int>v; int Find(int u){return (f[u]==u)?u:f[u]=Find(f[u]);} void kruscal(int no)//思维的妙处呀,本来想用type表示取红还是蓝,然后绿都可以,现在传一个no只要判断不是no就可以! { v.clear(); int Ecnt=0,ret=0,Euse=0; per(i,1,n)f[i]=i; for(int i=1;i<n;){ if(Ecnt>=m)return ; tmp=edge[Ecnt++]; while(tmp.ch==no){ v.push_back(Ecnt-1); tmp=edge[Ecnt++]; if(Ecnt-1 >= m)return ; } if(Find(tmp.a)!=Find(tmp.b)){ ret+=tmp.w; Euse++; f[Find(tmp.b)]=Find(tmp.a); i++; } else {v.push_back(Ecnt-1);} } ans[Euse]=min(ans[Euse],ret);// while(!v.empty()){ tmp=edge[v.front()]; v.erase(v.begin()); ret+=tmp.w; //这里wa到爆,要注意,每种kruscal的ans都是先的取各自情况的边!!!所以min的时候不能直接用ans[Ecnt-1] ans[++Euse]=min(ans[Euse],ret);//因为这可能是另一种情况的边取法 } per(i,Ecnt,m-1){ret+=edge[i].w;ans[++Euse]=min(ans[Euse],ret);} } int main() { int T; scanf("%d",&T); int cas=0; while(T--){ cas++; scanf("%d %d",&n,&m); Enum=0; per(i,0,m)ans[i]=inf; char kd; per(i,1,m){ scanf("%d %d %d %c",&edge[Enum].a,&edge[Enum].b,&edge[Enum].w,&kd); if(kd==‘G‘)edge[Enum].ch=1; else if((kd==‘R‘))edge[Enum].ch=0; else edge[Enum].ch=2; Enum++; } sort(edge,edge+Enum); kruscal(0); kruscal(2); printf("Case #%d:\n",cas); per(i,1,m){ if(ans[i]==inf){printf("-1\n");continue;} else printf("%d\n",ans[i]); } } return 0; }
原文地址:https://www.cnblogs.com/WindFreedom/p/9427618.html
时间: 2024-10-04 03:47:45