题意就是求最小生成树和次小生成树
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<string> 7 #define cl(a,b) memset(a,b,sizeof(a)) 8 #define debug(x) cerr<<#x<<"=="<<(x)<<endl 9 using namespace std; 10 typedef long long ll; 11 12 const int maxn=1e2+10; 13 const int inf=0x3f3f3f3f; 14 15 int n,m; 16 int cost[maxn][maxn]; 17 int pre[maxn],lowc[maxn]; 18 int Max[maxn][maxn]; 19 bool vis[maxn]; 20 int used[maxn][maxn]; 21 22 int mst() 23 { 24 int ans=0; 25 cl(vis,false),cl(Max,0); 26 vis[1]=true,pre[1]=1,lowc[1]=0; 27 for(int i=2; i<=n; i++) 28 { 29 lowc[i]=cost[1][i]; 30 pre[i]=1; 31 } 32 for(int i=1; i<=n; i++) 33 { 34 int minc=inf; 35 int p=-1; 36 for(int j=1; j<=n; j++) 37 { 38 if(!vis[j]&&minc>lowc[j]) 39 { 40 minc=lowc[j]; 41 p=j; 42 } 43 } 44 // if(minc==inf) return -1; 45 if(p==-1) break; 46 ans+=minc; 47 for(int j=1; j<=n; j++) 48 if(vis[j]) 49 { 50 Max[j][p]=max(Max[j][pre[p]],cost[pre[p]][p]); 51 } 52 vis[p]=used[p][pre[p]]=used[pre[p]][p]=1; 53 for(int j=1; j<=n; j++) 54 { 55 56 if(!vis[j]&&lowc[j]>cost[p][j]) 57 { 58 lowc[j]=cost[p][j]; 59 pre[j]=p; 60 } 61 } 62 } 63 return ans; 64 } 65 66 void solve() 67 { 68 int ans=mst(); 69 int Min=inf; 70 for(int i=1; i<=n; i++) 71 { 72 for(int j=1; j<=n; j++) 73 { 74 if(cost[i][j]!=inf&&used[i][j]==0) 75 { 76 Min=min(Min,ans+cost[i][j]-Max[i][j]); 77 } 78 } 79 } 80 printf("%d %d ",ans,Min); 81 } 82 83 int main() 84 { 85 int T; 86 scanf("%d",&T); 87 while(T--) 88 { 89 cl(cost,inf),cl(used,-1); 90 scanf("%d%d",&n,&m); 91 for(int i=1; i<=n; i++) 92 { 93 cost[i][i]=0; 94 } 95 for(int i=0; i<m; i++) 96 { 97 int u,v,w; 98 scanf("%d%d%d",&u,&v,&w); 99 cost[u][v]=cost[v][u]=w; 100 used[u][v]=used[v][u]=0; 101 } 102 solve(); 103 } 104 return 0; 105 } 106 /* 107 108 2 109 5 8 110 1 3 75 111 3 4 51 112 2 4 19 113 3 2 95 114 2 5 42 115 5 4 31 116 1 2 9 117 3 5 66 118 9 14 119 1 2 4 120 1 8 8 121 2 8 11 122 3 2 8 123 8 9 7 124 8 7 1 125 7 9 6 126 9 3 2 127 3 4 7 128 3 6 4 129 7 6 2 130 4 6 14 131 4 5 9 132 5 6 10 133 134 */