题目:n个点,m条边,求最小生成树的值和次小生成树的值。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int inf=0x3f3f3f3f;
int g[105][105];
int dis[105];
int path[105][105];
bool used[105][105];
int pre[105];
int vis[105];
int n,m;
void init()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j)g[i][j]=0;
else g[i][j]=inf;
}
}
int prime()
{
memset(path,0,sizeof(path));
memset(vis,0,sizeof(vis));
memset(used,false,sizeof(used));
int i,j,u=1,v;
int tmp;
for(i=1;i<=n;i++)
{
dis[i]=g[1][i];
pre[i]=1;
}
vis[1]=1;
int ans=0;
for(i=1;i<n;i++)
{
v=u;
tmp=inf;
for(j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<tmp)
{
tmp=dis[j];
u=j;
}
}
vis[u]=1;
ans+=tmp;
used[u][pre[u]]=used[pre[u]][u]=true;
for(j=1;j<=n;j++)
{
if(vis[j]&&u!=j)
{
path[u][j]=path[j][u]=max(path[j][pre[u]],dis[u]);
}
if(!vis[j])
{
if(dis[j]>g[u][j])
{
dis[j]=g[u][j];
pre[j]=u;
}
}
}
}
return ans;
}
int secondprime(int t)
{
int i,j,ans=inf;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i!=j&&!used[i][j])
{
ans=min(ans,t-path[i][j]+g[i][j]);
}
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int i,j;
int x,y,z;
init();
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
g[x][y]=g[y][x]=z;
}
int ans=prime();
int ans1=secondprime(ans);
printf("%d %d\n",ans,ans1);
}
return 0;
}