??xml version="1.0" encoding="utf-8" standalone="yes"?>
//思\Q本质是找从 A ?B 的最短\径,如果最短\径存在则一定会用满题意的按最次数的按钮
//如果最短\径不存在肯定找不刎ͼ输出 -1
//q里可以到辄点设?1, 是因为如果可以到辑ְ按了一下按钮,如果不可到达则仍然是MAX
//此题中如果有某一个点找不到到辑֮的最短\径,说明甉|到达q一层之后不可能再达到其他Q何了Q所以returnq回d数检查;q是和模板不同的地方
#include <iostream>
#include <string>
using namespace std;
#define MAXN 99999999
int button[201]; //存储每一层按下按钮之后可升降的层?/span>
int map[201][201]; 
int dist[201];
int visit[201];
int n, a, b;
void dijkstra ()

{
for (int i = 1; i <= n; i ++)
{
dist[i] = map[a][i]; //初值是L到每个点的距!
}
dist[a] = 0;
int k, min;
for ( int i = 1; i <= n; i ++ )
{
min = MAXN;
for (int j = 1; j <= n; j ++)
{
if ( !visit[j] && dist[j] < min ) //找最短的距离 
{
min = dist[j];
k = j;
}
}
if ( min == MAXN ) //没有最短\?nbsp; // 序
return ;
visit[k] = 1;
for (int j = 1; j <= n; j ++)
{
if ( !visit[j] && map[k][j] + dist[k] < dist[j] )
{
dist[j] = map[k][j] + dist[k];
}
}
}
}
int main ()

{
while ( scanf ("%d", &n) != EOF && n )
{
scanf ( "%d %d", &a, &b );
memset ( button, 0, sizeof (button) );
memset ( dist, 0, sizeof (dist) );
memset ( visit, 0, sizeof (visit) );
for ( int i = 1; i <= n; i ++ )
{
for ( int j = 1; j <= n; j ++ )
{
map[i][j] = MAXN;
}
}
for ( int i = 1; i <= n; i ++ )
{
scanf ("%d", &button[i]);
if ( i + button[i] <= n )
{
map[i][i + button[i]] = 1;
}
if ( i - button[i] >= 1 ) //最大的错误不是else if啊!Q!Q?nbsp;
{
map[i][i - button[i]] = 1;
}
}
dijkstra ();
if ( dist[b] < MAXN ) //有\径到?br>
printf ("%d\n", dist[b]);
else
printf ("%d\n", -1);
}
//system ("pause");
return 0;
}
]]>
心得Q利用ƈ查积 ?kruskal法l合找最短\径可以查找的效率更?br>本题的关键是正确地设定好两个数组Q一个是用于存放点边值的node1Q另一个是用于q查U处理的node2Qƈ且将q两个数l联pd
加入集合中的辚w是构成最生成树的边Q所以每家一ơsum 都要加上q两个顶点之间的距离
#include <iostream>
#include <string>
using namespace std;
struct node1 //用于存放点和边?nbsp;

{
int x;
int y;
int distance;
};
node1 edge[5010]; // n 个顶点的Ҏ向图最多有 n * (n - 1) / 2 条边 
struct node2 //q查U数l?nbsp;

{
int parent;
int height;
};
node2 village[100];
bool cmp ( const node1 &a, const node1 &b )

{
return a.distance < b.distance;
}
//q查U初始化
void set ( int n )

{
for ( int i = 1; i <= n; i++)
{
village[i].parent = i;
}
}
//找根节点
int findfather (int a)

{
while ( a != village[a].parent ) //理解while 树状l构Q找到最l的跟节?/span>
a = village[a].parent;
return a;
}
//合ƈ到同一集合
void merge (int a, int b) //注意参数Q要合ƈ两个节点的根 

{
if ( village[a].height == village[b].height )
{
village[b].parent = a;
village[a].height ++;
}
//树合ƈ到大?nbsp;
else if ( village[a].height > village[b].height ) 
{
village[b].parent = a;
}
else
village[a].parent = b;
} 
int main ()

{
int n, k;
int x, y, d;
int a, b;
while ( scanf ("%d", &n ) != EOF && n )
{
set ( n );
memset ( edge, 0, sizeof (edge) );
//输入处理
k = n * ( n - 1 ) / 2;
for ( int i = 0; i < k; i ++ )
{
scanf ( "%d %d %d", &x, &y, &d );
edge[i].x = x;
edge[i].y = y;
edge[i].distance = d;
}
//排序
sort ( edge, edge + k, cmp );
//从已排好的序列中选出最短边同时利用q查U构建图
int sum = 0;
for ( int i = 0; i < k; i++ )
{
a = findfather ( edge[i].x );
b = findfather ( edge[i].y );
if ( a != b )
{
merge ( a, b );
sum += edge[i].distance;
}
}
printf ( "%d\n", sum );
}
//system ("pause");
return 0;
}
]]>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <string.h>
5
6
int main ()
7

{
8
int n, q, a, b;
9
int lowcost[101]; //开始时储存源点到其他各点的边|随后Ҏ加进来的点Q不断改变所存的边?nbsp;
10
int edge[101][101]; //存输入的边之间的长度
11
int visit[101]; //标志点是否已经加入
12
13
while ( scanf ("%d", &n)!= EOF )
14
{
15
memset (visit, 0, sizeof (visit));
16
memset (lowcost, 0, sizeof (lowcost));
17
18
//输入处理
19
for (int i = 1; i <= n; i ++)
20
{
21
for (int j = 1; j<= n; j ++)
22
{
23
scanf ("%d", &edge[i][j]);
24
}
25
}
26
scanf ("%d", &q);
27
if ( q )
28
{
29
for (int i = 0; i < q; i ++) //本n存在边则该顶点被标记
30
{
31
scanf ("%d %d", &a, &b);
32
edge[a][b] = edge[b][a] = 0;
33
}
34
}
35
36
//prime:每次都从剩下的边中选出最短的一条,标记相关的顶点,q且修改相关边的?nbsp;
37
//对lowcost q行初始化处?/span>
38
for (int i = 1; i <= n; i ++ )
39
{
40
lowcost[i] = edge[1][i];
41
}
42
43
int sum = 0;
44
int k;
45
for (int i = 1; i <= n; i ++)
46
{
47
int max = 10000;
48
49
for ( int i = 1; i <= n; i ++ )
50
{
51
if ( lowcost[i] < max && !visit[i] )
52
{
53
max = lowcost[i];
54
k = i;
55
}
56
}
57
58
if (max == 10000) //如果没有扑ֈ最的边一下一个顶点作v?nbsp; Q这是和找最短\径不同的地方
59
break;
60
61
visit[k] = 1;
62
sum += lowcost[k];
63
64
for (int i = 1; i <= n; i ++)
65
{
66
if ( !visit[i] && lowcost[i] > edge[k][i]) //新引入的点到其他顶点的边?nbsp; 是否 于 原来的边?nbsp;
67
{
68
lowcost[i] = edge[k][i];
69
}
70
}
71
}
72
printf ("%d\n", sum);
73
}
74
// system ("pause");
75
return 0;
76
}
77
]]>
//奉献了好多次的WA l果是因为在已有边存在的地方只讑֮?nbsp;edge[a][b] = 0; 出错
本题的关键运用在于辅助数l?lowcost[ ] 的?br>

2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <string.h>
5
6
int main ()
7
{
8
int n, q, a, b;
9
int lowcost[101]; //开始时储存源点到其他各点的边|随后Ҏ加进来的点Q不断改变所存的边?nbsp;
10
int edge[101][101]; //存输入的边之间的长度
11
int visit[101]; //标志点是否已经加入
12
13
while ( scanf ("%d", &n)!= EOF )
14
{
15
memset (visit, 0, sizeof (visit));
16
memset (lowcost, 0, sizeof (lowcost));
17
18
//输入处理
19
for (int i = 1; i <= n; i ++)
20
{
21
for (int j = 1; j<= n; j ++)
22
{
23
scanf ("%d", &edge[i][j]);
24
}
25
}
26
scanf ("%d", &q);
27
if ( q )
28
{
29
for (int i = 0; i < q; i ++) //本n存在边则该顶点被标记
30
{
31
scanf ("%d %d", &a, &b);
32
edge[a][b] = edge[b][a] = 0;
33
}
34
}
35
36
//prime:每次都从剩下的边中选出最短的一条,标记相关的顶点,q且修改相关边的?nbsp;
37
//对lowcost q行初始化处?/span>
38
for (int i = 1; i <= n; i ++ )
39
{
40
lowcost[i] = edge[1][i];
41
}
42
43
int sum = 0;
44
int k;
45
for (int i = 1; i <= n; i ++)
46
{
47
int max = 10000;
48
49
for ( int i = 1; i <= n; i ++ )
50
{
51
if ( lowcost[i] < max && !visit[i] )
52
{
53
max = lowcost[i];
54
k = i;
55
}
56
}
57
58
if (max == 10000) //如果没有扑ֈ最的边一下一个顶点作v?nbsp;
59
break;
60
61
visit[k] = 1;
62
sum += lowcost[k];
63
64
//修改要加入的点到其他未加入点之间的距?br> for (int i = 1; i <= n; i ++)
65
{
66
if ( !visit[i] && lowcost[i] > edge[k][i]) //新引入的点到其他顶点的边?nbsp; 是否 于 原来的边?nbsp;
67
{
68
lowcost[i] = edge[k][i];
69
}
70
}
71
}
72
printf ("%d\n", sum);
73
}
74
// system ("pause");
75
return 0;
76
}
77
]]>