UVA 10462 (带重边的次小生成树)
prim 求次小生成树时采用的是维护一个数组 此数组用来保存最小生成树中i到j的最大边值,每次加入一个新的节点 用动态规划的思想 maxab[i][j]=maxab[j][i]=max(maxab[per[i]][j],dis[i]);即可。
但是此题 带重边 我们如果要使用prim 则需要用邻接链表来存储边的信息。
但是kruskal可以避免这种情况 直接采用加边的方法;
kruskal的maxab数组的更新不能 直接更新
因为每次加进去的边 不一定使得之前的边与此边相连接
所以每一次要采用
每加入一条边都要更新与其相连的所有节点之间的maxab;
因为kruskal边的权值递增的所以 更新时直接等于要加的这条边的权值;
maxab[p[fx][x]][p[fy][y]]=maxab[p[fy][y]][p[fx][x]]=E[i].v;
代码
//带重边的次小生成树 kruskal
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=0x3f3f3f3f;
struct edge{
int b,e,v,vis;
}E[205];//保存边的信息
int ans,ans1;
int per[105];
int maxab[105][105];
vector <int> p[105];
void init(){ //初始化
for(int i=0;i<105;i++){
per[i]=i;
p[i].clear();
p[i].push_back(i);
for(int j=0;j<105;j++){
maxab[i][j]=0;
}
}
for(int i=0;i<205;i++){
E[i].vis=0;
}
ans=0;ans1=maxn;
}
int find (int x){ //并查集
int r=x;
while(r!=per[r]){
r=per[r];
}
return r;
}
bool compare (struct edge a,struct edge b){
if(a.v!=b.v)return a.v<b.v;
if(a.b!=b.b)return a.b<b.b;
return a.e<b.e;
}
bool kruskal(int m,int n){
int k=0;
if(k==n-1)return true;
for(int i=1;i<=m;i++){
if(k==n-1)return true;
int fx=find(E[i].b);
int fy=find(E[i].e);
if(fx!=fy){
k++;
E[i].vis=1;
ans+=E[i].v;
int xsize=p[fx].size();
int ysize=p[fy].size();
for(int x=0;x<xsize;x++){
for(int y=0;y<ysize;y++){
maxab[p[fx][x]][p[fy][y]]=maxab[p[fy][y]][p[fx][x]]=E[i].v;
}
}
per[fx]=fy;
for(int x1=0;x1<xsize;x1++){
p[fy].push_back(p[fx][x1]);
}
for(int x2=0;x2<ysize;x2++){
p[fx].push_back(p[fy][x2]);
}
}
}
if(k==n-1)return true;
return false;
}
void second(int m){
for(int i=1;i<=m;i++){
if(!E[i].vis){
ans1=min(ans-maxab[E[i].b][E[i].e]+E[i].v,ans1);
}
}
}
int main()
{
int t,n,m,cnt=0;
scanf("%d",&t);
while(t--){
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&E[i].b,&E[i].e,&E[i].v);
}
sort(E+1,E+m+1,compare);
printf("Case #%d : ",++cnt);
if(kruskal(m,n)){
/*for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++)
cout<<maxab[i][j]<<" ";
cout<<endl;
}*/
second(m);
if(ans1!=maxn)printf("%d\n",ans1);
else printf("No second way\n");
}
else printf("No way\n");
}
}