题目链接:
Is There A Second Way Left?
就是很单纯的判断次小生成树!!!
昨晚刚开始看,今天就考了!(关键是没做出来
说一下思路吧:先求出来最小生成树,然后每次去掉最小生成树上的一条边(枚举!)若能再求最小生成树!即为次小生成树!(可能估计次短路也是这样吧!!!
心累。。。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
struct Node{
int x;
int y;
int w;
}e[220];
int fa[220],path[220];
int n,m;
const int INF = 1e9;
void init()
{
for(int i=1;i<=n;i++)
fa[i] = i;
}
int find(int x)
{
if(x != fa[x])
fa[x] = find(fa[x]);
return fa[x];
}
bool cmp(Node a,Node b)
{
return a.w < b.w;
}
int main()
{
int T;
scanf("%d",&T);
int tot = 1;
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
}
printf("Case #%d : ",tot ++);
init();
int ans = 0;
int k = 0;
sort(e+1,e+1+m,cmp);
for(int i=1;i<=m;i++)
{
int r1 = find(e[i].x);
int r2 = find(e[i].y);
if(r1 != r2)
{
fa[r1] = r2;
ans += e[i].w;
path[k++] = i;
}
if(k == n-1)
break;
}
if(k != n-1)
{
printf("No way\n");
continue;
}
int num = INF;
for(int i=0;i<k;i++)
{
init();
int kk = 0,ans=0;
for(int j=1;j<=m;j++)
{
if(j == path[i])
continue;
int r1 = find(e[j].x);
int r2 = find(e[j].y);
if(r1 != r2)
{
fa[r1] = r2;
ans += e[j].w;
kk ++;
}
if(kk == n-1)
break;
}
if(kk == n-1)
num = min(ans,num);
}
if(num == INF)
{
printf("No second way\n");
}
else printf("%d\n",num);
}
return 0;
}
再补充一道题!
题目链接:The Unique MST(水!
昨晚自己是这样考虑的,先用克鲁斯卡尔求最小生成树,然后从最小的边开始遍历,如果发现这条最小的边链接的两个点已经链接好了,而且这条边的权值跟上一条边的权值相同的话,就一定存在最小生成树(事实整明这样考虑是错的,不过还能AC。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct Node{
int x;
int y;
int w;
}e[150000];
int fa[120000],path[120000];
const int INF = 1e9;
int T,n,m,x,y;
bool cmp(Node a,Node b)
{
return a.w < b.w;
}
int find(int x)
{
if(x != fa[x])
fa[x] = find(fa[x]);
return fa[x];
}
void init()
{
for(int i=0;i<=n;i++)
fa[i] = i;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
}
sort(e+1,e+1+m,cmp);
int ans1 = 0;
int k = 0;
for(int i=1;i<=m;i++)
{
int r1 = find(e[i].x);
int r2 = find(e[i].y);
if(r1 != r2)
{
fa[r1] = r2;
ans1 += e[i].w;
path[++k] = i;
}
if(k == n-1)
break;
}
int num = INF;
for(int i=1;i<=k;i++)
{
init();
int ans = 0;
int kk = 0;
for(int j=1;j<=m;j++)
{
if(j == path[i])
continue;
int r1 = find(e[j].x);
int r2 = find(e[j].y);
if(r1 != r2)
{
fa[r1] = r2;
ans += e[j].w;
kk ++;
}
if(kk == n-1)
break;
}
if(kk == n-1)
num = min(num,ans);
}
if(num == ans1)
printf("Not Unique!\n");
else printf("%d\n",ans1);
}
return 0;
}
602

被折叠的 条评论
为什么被折叠?



