UVA10600 ACM Contest and Blackout
用prim算法求最小生成树和次小生成树~
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1014; const int inf=1e9; int g[maxn][maxn],d[maxn],visit[maxn],pre[maxn],c[maxn][maxn],N,M; int path[maxn][maxn];//记录最小生成树里两点之间的路径 void init () { for (int i=0;i<maxn;i++) for (int j=0;j<maxn;j++) g[i][j]=inf,c[i][j]=0,path[i][j]=0; } int prim (int s) { fill (d,d+maxn,inf); fill (visit,visit+maxn,0); for (int i=1;i<=N;i++) pre[i]=i; d[s]=0; int ans=0; for (int i=1;i<=N;i++) { int u=-1,min=inf; for (int j=1;j<=N;j++) if (visit[j]==false&&d[j]<min) { u=j; min=d[j]; } if (u==-1) return -1; visit[u]=1; ans+=d[u]; if (pre[u]!=u) c[u][pre[u]]=c[pre[u]][u]=1; for (int v=1;v<=N;v++) { if (!visit[v]&&g[u][v]!=inf&&g[u][v]<d[v]) d[v]=g[u][v],pre[v]=u; if (visit[v]&&v!=u) path[u][v]=path[v][u]=max(path[pre[u]][v],d[u]); } } return ans; } int main () { int T; scanf ("%d",&T); while (T--) { scanf ("%d %d",&N,&M); int x,y; init (); for (int i=0;i<M;i++) { scanf ("%d %d",&x,&y); scanf ("%d",&g[x][y]); g[y][x]=g[x][y]; } int mst=prim (1); int ans=inf; for (int i=1;i<=N;i++) for (int j=1;j<=N;j++) { if (i!=j&&!c[i][j]) { ans=min(ans,mst-path[i][j]+g[i][j]); } } printf ("%d %d\n",mst,ans); } return 0; }