4
5 4
1 2 5
3 2 5
4 2 5
5 4 5
5 3
1 2 5
3 2 5
5 4 5
5 5
1 2 5
3 2 5
4 2 5
5 4 5
4 5 6
1 0
Case #1 : No second way
Case #2 : No way
Case #3 : 21
Case #4 : No second way
思路
求最短路和次短路,有最次路就输出长度。
Kruskal求最短路和次短路,判断是否存在。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
//Kruskal
using namespace std;
typedef long long ll;
const int N = 1e3+10;
struct node
{
int x,y;
int d;
} e[N*N];
bool cmp(node a,node b)
{
return a.d<b.d;
}
int pre[N];
int add[N];//记录所选取边的下标,add[1]表示选取第一条边的编号
int findd(int x)
{
if(x!=pre[x])
{
int t=findd(pre[x]);
pre[x]=t;
}
return pre[x];
}
bool judge(int x,int y)//判断并连接
{
int fx=findd(x),fy=findd(y);
if( fy != fx )
{
pre[fy] = fx ;
return 1 ;
}
return 0 ;
}
int n,m;
int kr(int x)//表示去掉第x条边求最短路
{
int ans=0,cnt=0;
for(int i=1; i<=n; i++)//初始化
pre[i]=i;
for(int i=1; i<=m; i++)
{
if(i==x)continue;
if(judge(e[i].x,e[i].y))
{
ans+=e[i].d;
cnt++;
if(x==0)add[cnt]=i;//x==0表示不去边求最短路,记录所选的边
}
if(cnt==n-1)return ans;//如果存在次短路就输出
}
return -1;
}
ll ans;
int main()
{
int t;
scanf("%d",&t);
for( int j=1; j<=t; j++)
{
scanf("%d%d",&n,&m);
memset( pre, 0, sizeof(pre) );
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].d);
}
sort(e+1,e+1+m,cmp);
int ans1=kr(0);//最短路
int ans2=1e9;//次短路
for(int i=1; i<n; i++)
{
if(kr(add[i])!=-1)
{
if(ans2>kr(add[i]))ans2=kr(add[i]);//记录次短路
}
}
printf("Case #%d : ",j);
if( n == 1 && m == 0 )
{
cout<<"No second way"<<endl ;
continue;
}
if(ans2!=1e9)
printf("%d\n",ans2);
else if(ans2==1e9&&ans1!=-1)
printf("No second way\n");
else if(ans2==1e9&&ans1==-1)
printf("No way\n");
}
return 0;
}