这个题求最小有向生成树,基本上就是朱刘算法模板。
代码:
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> using namespace std; const int inf=1<<29; const int maxn=1100; const int maxm=5e4; struct Edge { int u; int v; int c; }E[maxm]; int n,m,pre[maxm],ID[maxm],vis[maxm],cnt[maxn]; int In[maxm]; int Directed_MST(int root,int NV,int NE) { int ret=0; while(1) { //1、找最小入边 for(int i=0;i<NV;i++) In[i]=inf; for(int i=0;i<NE;i++) { int u=E[i].u; int v=E[i].v; if(E[i].c<In[v]&&u!=v) { pre[v]=u; In[v]=E[i].c; } } for(int i=0;i<NV;i++) { if(i==root) continue; if(In[i]==inf) return -1; } //2、找环 int cntnode=0; memset(ID,-1,sizeof(ID)); memset(vis,-1,sizeof(vis)); In[root]=0; for(int i=0;i<NV;i++) { ret+=In[i]; int v=i; while(vis[v]!=i&&ID[v]==-1&&v!=root) { vis[v]=i; v=pre[v]; } if(v!=root&&ID[v]==-1) { for(int u=pre[v];u!=v;u=pre[u]) { ID[u]=cntnode; } ID[v]=cntnode++; } } if(cntnode==0) break;//无环 for(int i=0;i<NV;i++) if(ID[i]==-1) { ID[i]=cntnode++; } //3.缩点,重新标记 for(int i=0;i<NE;i++) { int v=E[i].v; E[i].u=ID[E[i].u]; E[i].v=ID[E[i].v]; if(E[i].u!=E[i].v) { E[i].c-=In[v]; } } NV=cntnode; root=ID[root]; } return ret; } int main() { int T,cas=1; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); memset(cnt,0,sizeof(cnt)); for(int i=0;i<m;i++) { scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].c); cnt[E[i].v]++; } int ans=Directed_MST(0,n,m); if(ans==-1) printf("Case #%d: Possums!\n",cas++); else printf("Case #%d: %d\n",cas++,ans); } return 0; }