UVA 10600 & 次小生成树

这道题涉及次小生成树,有必要先弄明白次小生成树是怎么一回事。

次小生成树,顾名知义。一个定理是,次小生成树可以由最小生成树交换一条边得到。这怎么证明,可以上网搜一下。但有必要提醒的是,交换过来的这样一条边,必须是未成使用过的(即不是最小生成树的边)。而且,交换走的边,必须是已存在的,而且是两点间最短路径的最大边权的边。

所以,可以在求最小生成树时求这最大边权的边。

 1 void prim(){
 2     memset(f,0,sizeof(f));
 3     least[1]=0;
 4     for(int i=2;i<=n;i++){
 5         least[i]=map[1][i];
 6         if(least[i]!=inf)
 7         pre[i]=1;
 8     }
 9     vis[1]=true;
10     for(int i=1;i<=n;i++){
11         int min=inf,p=-1;
12         for(int k=1;k<=n;k++){
13             if(least[k]<min&&!vis[k]){
14                 p=k; min=least[k];
15             }
16         }
17 
18         if(p==-1) return ;
19         ans1+=min;
20         used[pre[p]][p]=used[p][pre[p]]=1;
21         for(int j=1;j<=n;j++){ //应该是已访问的点,这样边是已使用
22         if(vis[j])
23         f[j][p]=max(f[j][pre[p]],map[pre[p]][p]);
24         f[p][j]=f[j][p];
25         }
26         vis[p]=true;
27         for(int k=1;k<=n;k++){
28             if(!vis[k]&&map[p][k]<least[k]){
29                 least[k]=map[p][k];
30                 pre[k]=p;
31             }
32         }
33     }
34 }
View Code

UV10600是裸的次小生成树题。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 const int MAXN=105;
 8 const int inf=10000000;
 9 int map[MAXN][MAXN]; int f[MAXN][MAXN];
10 bool exist[MAXN][MAXN],used[MAXN][MAXN];
11 int least[MAXN],pre[MAXN]; bool vis[MAXN]; 
12 int n,m,ans1,ans2;
13 
14 void prim(){
15 memset(f,0,sizeof(f));
16 least[1]=0;
17 for(int i=2;i<=n;i++){
18 least[i]=map[1][i];
19 if(least[i]!=inf)
20 pre[i]=1;
21 }
22 vis[1]=true;
23 for(int i=1;i<=n;i++){
24 int min=inf,p=-1;
25 for(int k=1;k<=n;k++){
26 if(least[k]<min&&!vis[k]){
27 p=k; min=least[k];
28 }
29 }
30 
31 if(p==-1) return ;
32 ans1+=min;
33 used[pre[p]][p]=used[p][pre[p]]=1;
34 for(int j=1;j<=n;j++){
35 if(vis[j])
36 f[j][p]=max(f[j][pre[p]],map[pre[p]][p]);
37 f[p][j]=f[j][p];
38 }
39 vis[p]=true;
40 for(int k=1;k<=n;k++){
41 if(!vis[k]&&map[p][k]<least[k]){
42 least[k]=map[p][k];
43 pre[k]=p;
44 }
45 }
46 }
47 }
48 
49 void secondT(){
50 ans2=inf;
51 for(int i=1;i<=n;i++){
52 for(int j=1;j<=n;j++){
53 if(exist[i][j]&&!used[i][j]&&ans1 + map[i][j] - f[i][j] < ans2)
54 ans2=ans1 + map[i][j] - f[i][j];
55 }
56 }
57 }
58 
59 int main(){
60 int T; 
61 scanf("%d",&T);
62 while(T--){
63 scanf("%d%d",&n,&m);
64 int u,v,d;
65 ans1=ans2=0;
66 memset(exist,-1,sizeof(exist));
67 for(int i=1;i<=n;i++){
68 for(int j=i;j<=n;j++)
69 map[i][j]=map[j][i]=inf;
70 }
71 for(int i=1;i<=m;i++){
72 scanf("%d%d%d",&u,&v,&d);
73 map[u][v]=map[v][u]=d;
74 exist[u][v]=exist[v][u]=1;
75 }
76 memset(pre,-1,sizeof(pre));
77 memset(used,0,sizeof(used));
78 memset(vis,false,sizeof(vis));
79 prim();
80 secondT();
81 printf("%d %d\n",ans1,ans2);
82 }
83 return 0;
84 }
View Code
posted @ 2014-07-18 08:42  chenjunjie1994  阅读(164)  评论(0编辑  收藏  举报