[关键字]:次小生成树
[题目大意]:求出给出图的最小和次小生成树。
//=============================================================================
[分析]:http://www.cppblog.com/MatoNo1/archive/2011/06/25/147627.html#149420讲的又清楚又详细,ORZMato大神!
[代码]:
kurscal
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int INF=1000000; const int MAXN=1000; const int MAXM=130000; struct node { int x,y,d,p,next,no; }e[MAXM],E[MAXM+MAXM]; int n,m,M,ans1,ans2,tot,now=INF,h,t; int f[MAXN],s[MAXN],nx[MAXN],q[MAXM]; bool cmp(node a,node b){return a.d<b.d;} void Init_d() { for (int i=1;i<=n;++i) E[i].x=E[i].next=E[i].p=i; if (n&1) M=n+1; else M=n+2; } void Add(int x,int y,int z) { E[M].x=x,E[M].y=y,E[M].d=z,E[M].p=E[x].p,E[M].next=x,E[x].p=M,E[E[M].p].next=M++; E[M].x=y,E[M].y=x,E[M].d=z,E[M].p=E[y].p,E[M].next=y,E[y].p=M,E[E[M].p].next=M++; } void Del(int NO) { E[E[NO].p].next=E[NO].next,E[E[NO].next].p=E[NO].p; E[E[NO^1].p].next=E[NO^1].next,E[E[NO^1].next].p=E[NO^1].p; } void Init() { scanf("%d%d",&n,&m); if (!m) if (n>1){ans1=ans2=INF;return;} Init_d(); for (int i=1;i<=m;++i) { int x,y,z; scanf("%d%d%d",&x,&y,&z); e[i].no=M,Add(x,y,z); e[i].x=x,e[i].y=y,e[i].d=z; } } int GET(int v) { if (f[v]<0) return v; f[v]=GET(f[v]); return f[v]; } void Union(int r1,int r2,int NO,int l0) { //printf("%d\n",NO); q[h=t=0]=r1; while (h<=t) { int u=q[h++]; for (int i=s[u];i!=-1;i=nx[i]) q[++t]=i; } for (int i=0;i<=t;++i) { int u=q[i]; for (int j=E[u].next;j!=u;j=E[j].next) { int v=E[j].y; if (j!=NO && GET(v)==r2) { int temp=E[j].d-l0; if (temp<now) now=temp;//,printf("%d %d\n",j,NO); Del(j); } } } f[r2]+=f[r1],f[r1]=r2,nx[r1]=s[r2],s[r2]=r1; } void Solve() { for (int i=1;i<=n;++i) f[i]=s[i]=nx[i]=-1; sort(e+1,e+m+1,cmp); /*for (int i=1;i<=m;++i) printf("%d %d %d %d\n",e[i].x,e[i].y,e[i].d,e[i].no);*/ for (int i=1;i<=m;++i) { int r1=GET(e[i].x),r2=GET(e[i].y); if (r1!=r2) { //printf("%d %d %d %d %d\n",r1,r2,e[i].x,e[i].y,e[i].d); ans1+=e[i].d,++tot; //printf("%d\n",e[i].no); if (f[r1]>=f[r2]) Union(r1,r2,e[i].no,e[i].d); else Union(r2,r1,e[i].no^1,e[i].d); } } //printf("%d\n",now); if (tot<n-1) ans1=ans2=INF; if (now==INF) ans2=INF; else ans2=ans1+now; if (ans1==INF) ans1=-1;if (ans2==INF)ans2=-1; printf("Cost: %d\nCost: %d\n",ans1,ans2); } int main() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); Init(); /*printf("%d\n",M); for (int i=1;i<=M;++i) printf("%d %d %d %d %d\n",E[i].x,E[i].y,E[i].d,E[i].p,E[i].next); for (int i=1;i<=m;++i) printf("%d %d %d %d\n",e[i].x,e[i].y,e[i].d,e[i].no);*/ if (!ans1) Solve(); return 0; }
prim
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int INF=10000000; const int MAXN=510; int n,m,ans1,ans2,now; int s[MAXN][MAXN],s2[MAXN][MAXN]; int f[MAXN][MAXN],d[MAXN],p[MAXN]; bool vis[MAXN]; void Init() { scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) { p[i]=i; for (int j=1;j<=n;++j) s[i][j]=s2[i][j]=INF; } /*for (int i=1;i<=n;++i) { for (int j=1;j<=n;++j) printf("%d ",s2[i][j]); printf("\n"); }*/ if (!m) if (n>1) {ans1=ans2=INF;return;} for (int i=1;i<=m;++i) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if (z<s[x][y]) s2[x][y]=s2[y][x]=s[x][y],s[x][y]=s[y][x]=z; else if (z<s2[x][y]) s2[x][y]=z; //printf("%d %d %d %d %d\n",x,y,z,s[x][y],s2[x][y]); } /*for (int i=1;i<=n;++i) { for (int j=1;j<=n;++j) printf("%d ",s2[i][j]); printf("\n"); }*/ } void Solve() { for (int i=1;i<=n;++i) vis[i]=0,d[i]=INF; d[1]=0,now=INF; for (int i=1;i<=n;++i) { int Min=INF,Minj; for (int j=1;j<=n;++j) if (!vis[j] && Min>d[j]) Min=d[Minj=j]; if (Min==INF) {ans1=ans2=INF;return;} vis[Minj]=1,ans1+=Min; s[p[Minj]][Minj]=s[Minj][p[Minj]]=INF; if (s2[p[Minj]][Minj]<INF && s2[p[Minj]][Min]-Min<now) now=s2[p[Minj]][Min]-Min; for (int j=1;j<=n;++j) if (!vis[j] && d[j]>s[Minj][j]) d[j]=s[Minj][j],p[j]=Minj; for (int j=1;j<=n;++j) if (vis[j] && j!=Minj) f[j][Minj]=f[Minj][j]=max(f[j][p[Minj]],Min); //printf("%d %d\n",Min,Minj); } //printf("%d\n",now); for (int i=1;i<n;++i) for (int j=i+1;j<=n;++j) if (s[i][j]<INF) { int temp=s[i][j]-f[i][j]; if (temp<now) now=temp; } if (now==INF) ans2=INF; else ans2=ans1+now; if (ans1==INF) ans1=-1; if (ans2==INF) ans2=-1; printf("Cost: %d\nCost: %d\n",ans1,ans2); } int main() { freopen("in","r",stdin); freopen("out","w",stdout); Init(); if (!ans2) Solve(); return 0; }