酷暑一夏1

不忘初心,方得始终


Vijos1070 新年趣事之游戏 题解

题目

xiaomengxian的哥哥是一个游戏迷,他喜欢研究各种游戏。这天,xiaomengxian到他家玩,他便拿出了自己最近正在研究的一个游戏给xiaomengxian看。这个游戏是这样的:一个国家有N个城市,有些城市之间可以建设铁路,并且不同城市之间建设铁路的费用各不相同。问如何用最小的费用,使整个国家的各个城市之间能够互相到达。另外,铁路是双向的。xiaomengxian心想,这不是太简单了吗?这就是经典的MST问题。他的哥哥说,这个当然不算什么。关键是它还要求费用第二小的方案,这真是让人伤脑筋。xiaomengxian想了很久,也没有想出来,你能帮助他吗?
费用第二小的方案的定义为:与费用最小的方案不完全相同,且费用值除费用最小的方案外最小。

题解

次小生成树

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<cstdio>
#include<algorithm>
const int MAXN=500+5;
const int MAXM=250000+5;
struct Edge{int u,v,w;bool disabled;};
int n,m,father[MAXN],totsel,sel[MAXM];Edge edge[MAXM];
bool comp(Edge a,Edge b){return a.w<b.w;}
int find(int x){return x==father[x]?x:father[x]=find(father[x]);}
int Kruskal(int flag)
{
int ans=0;
for(int i=1;i<=n;i++)
father[i]=i;
int l=1;
for(int i=1;i<=m;i++)
{
if(edge[i].disabled) continue;
int fx=find(edge[i].u),fy=find(edge[i].v);
if(fx!=fy)
{
if(flag) sel[++totsel]=i;
father[fx]=fy;
ans+=edge[i].w;
l++;
}
if(l==n) return ans;
}
return 2147483647;
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);
std::sort(edge+1,edge+m+1,comp);
int ans=Kruskal(1);
if(ans==2147483647)
{
printf("Cost: -1\nCost: -1");
return 0;
}
printf("Cost: %d\n",ans);
ans=2147483647;
for(int i=1;i<=totsel;i++)
{
edge[sel[i]].disabled=1;
ans=std::min(ans,Kruskal(0));
edge[sel[i]].disabled=0;
}
printf("Cost: %d",ans==2147483647?-1:ans);
return 0;
}
最近的文章

Vijos1068 新年趣事之玩具 题解

题目今年春节,xiaomengxian回到了邵阳过年。刚准备进门时,突然发现院子里有个小孩在摆弄什么东西。走进一看,原来他在玩一种智力玩具,叫做“汉诺塔”。“汉诺塔”是这样一种玩具:有三个柱子,分别编号:#1,#2,#3。初始时,有N个直径不同的盘子放在第一根柱子上,且越底下的盘子直径越大。游戏的目 …

于  Vijos, 新年趣事系列 继续阅读
更早的文章

Vijos1415 生命游戏 题解

题目生命游戏(Game of life)由英国数学家John Conway在1970年发明。事实上,它是一个“零人游戏”,也没有胜负之分,而是相当于一个确定性自动机。游戏在N×M的细胞组成的矩阵里进行,每个细胞每个时刻的状态可能是“存活”或者“休眠”两种,细胞矩阵的状态会按以下规则进行演化:一个存活 …

于  Vijos 继续阅读