Description
BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchical communication subsystem. Valentine McKee’s research advisor, Jack Swigert, has asked her to benchmark the new system.
``Since the Apollo is a distributed shared memory machine, memory 。。。。巴拉巴拉一堆对话,不影响题意。
输入描述:
The input will describe the topology of a network connecting n processors. The first line of the input will be n, the number of processors, such that 1 <= n <= 100.
The rest of the input defines an adjacency matrix, A. The adjacency matrix is square and of size n x n. Each of its entries will be either an integer or the character x. The value of A(i,j) indicates the expense of sending a message directly from node i to node j. A value of x for A(i,j) indicates that a message cannot be sent directly from node i to node j.
Note that for a node to send a message to itself does not require network communication, so A(i,i) = 0 for 1 <= i <= n. Also, you may assume that the network is undirected (messages can go in either direction with equal overhead), so that A(i,j) = A(j,i). Thus only the entries on the (strictly) lower triangular portion of A will be supplied.
The input to your program will be the lower triangular section of A. That is, the second line of input will contain one entry, A(2,1). The next line will contain two entries, A(3,1) and A(3,2), and so on.
输出描述:
Your program should output the minimum communication time required to broadcast a message from the first processor to all the other processors.
Sample:
输入 :
5
50
30 5
100 20 50
10 x x 10
输出:
35
题意解析
题目看着挺长,但意思就是求一个点在图内broadcast一遍的最短的时间,那就是到最远点的最短时间
放到最短路径问题中,也就是求出源点到每个其他点的最短路径,其中最长的就是最终我们要求的广播最短时间。
最后这里还有一个输入格式的问题,输入的值是无向图邻接矩阵A[N][N],由于每一个点到自己本身都是0所以省略不输入,由于A[i][j]=A[j][i]所以只输入一半的值,然后x表示该路径不通,最后形成的输入数据就是上面样例的样子:
5
50
30 5
100 20 50
10 x x 10
然后我们就通过一些操作成功得到最后的邻接矩阵A[N][N]了。
看到单源最短路径,大家应该一下子就能想到Dijkstra这个经典永流传的算法,那么接下来,我们通过队列式分支限界法广搜和优先队列式分支限界法广搜以及Dijkstra算法分别求出单源最短路径来解这道题。
1.队列式分支限界法广搜
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
using namespace std;
#define N 105
int n;
int A[N][N];
int dist[N];//当前距离
int cnt;
struct Node {
int vi;//点编号
int len;//源至该点当前最短距离
Node(int vi0 = 0, int len0 = 0) :vi(vi0), len(len0) {}
};
void bfs() {
queue<Node> Q;
Q.push(Node(1, 0));
while (!Q.empty()) {
Node ft = Q.front();
Q.pop();
//对于该点,先尝试往外拓展,看看通过ft.vi这个点能不能比现在有更优的走法,有的话就拓展出去
for (int i = 1; i <= n; i++) {
if (A[ft.vi][i] > 0 && dist[ft.vi] + A[ft.vi][i] < dist[i]) {
cnt++;//仅仅作入队情况参考,与本题无关,可以删去
dist[i] = dist[ft.vi] + A[ft.vi][i];
Q.push(Node(i, dist[i]));
}
}
}
}
int main()
{
string s;
cin >> n;
getchar();
for (int i = 2; i <= n; i++) {
getline(cin, s);
int k = 0;
for (int j = 1; j <= i - 1; j++) {
int t = 0;
while (s[k] != ' ' && s[k] != '\0') {
if (s[k] == 'x') {
t = -1;
}
else t = t * 10 + (s[k] - '0');
k++;
}k++;
A[i][j] = t;
A[j][i] = A[i][j];
if (j == 1) {
dist[i] = 0x3f3f3f3f;//先初始化所有点路径长度为最大以便比较更新
}
}
}
dist[1] = 0;//当然第一个结点到自己的距离为0
//以上代码主要为输入,接下来bfs广搜
bfs();
//接下来查找最远的结点
int maxlen = 0;
for (int i = 1; i <= n; i++) {
maxlen = max(maxlen, dist[i]);
}
cout << maxlen << endl;
//cout << "cnt=" << cnt << endl;//cnt可以看看队列里一共入了多少点
return 0;
}
2.优先队列式分支限界法广搜
//思路与队列式类似
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
using namespace std;
#define N 105
int n;
int A[N][N];
int dist[N];//当前距离
int cnt;
struct Node {
int vi;//点编号
int len;//源至该点当前最短距离
Node(int vi0 = 0, int len0 = 0) :vi(vi0), len(len0) {}
bool operator > (const Node& b)const {
return len > b.len;
}
};
void bfs() {
priority_queue<Node,vector<Node>,greater<Node> > Q;//最小堆优先队列
Q.push(Node(1, 0));
while (!Q.empty()) {
Node ft = Q.top();
Q.pop();
for (int i = 1; i <= n; i++) {
if (A[ft.vi][i] > 0 && dist[ft.vi] + A[ft.vi][i] < dist[i]) {
cnt++;
dist[i] = dist[ft.vi] + A[ft.vi][i];
Q.push(Node(i, dist[i]));
}
}
}
}
int main()
{
string s;
cin >> n;
getchar();
for (int i = 2; i <= n; i++) {
getline(cin, s);
int k = 0;
for (int j = 1; j <= i - 1; j++) {
int t = 0;
while (s[k] != ' ' && s[k] != '\0') {
if (s[k] == 'x') {
t = -1;
}
else t = t * 10 + (s[k] - '0');
k++;
}k++;
A[i][j] = t;
A[j][i] = A[i][j];
if (j == 1) {
dist[i] = 0x3f3f3f3f;
}
}
}
dist[1] = 0;
bfs();
int maxlen = 0;
for (int i = 1; i <= n; i++) {
maxlen = max(maxlen, dist[i]);
}
cout << maxlen << endl;
//cout << "cnt=" << cnt << endl;//cnt可以看看队列里一共入了多少点
return 0;
}
3.Dijkstra算法
//简单的dijkstra实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
using namespace std;
#define N 105
int n;
int A[N][N];
int dist[N];//当前距离
int cnt;
void Dijkstra(int v) {
vector<bool> s(n + 1, false);
for (int i = 1; i <= n; i++) {
dist[i] = A[v][i];
if (dist[i] < 0) {
dist[i] = 0x3f3f3f3f;
}
}
s[v] = true;
for (int i = 1; i < n; i++) {
int u = v;
int Min = 0x3f3f3f3f;//找出集合S外最近的点u
for (int j = 1; j <= n; j++) {
if (!s[j] && dist[j] < Min) {
Min = dist[j];
u = j;
}
}
s[u] = true;//u入集合
for (int j = 1; j <= n; j++) {//根据新加入点更新到其他点距离
if (!s[j] && dist[u] + A[u][j] < dist[j] && A[u][j]>0) {
dist[j] = dist[u] + A[u][j];
}
}
}
}
int main()
{
string s;
cin >> n;
getchar();
for (int i = 2; i <= n; i++) {
getline(cin, s);
int k = 0;
for (int j = 1; j <= i - 1; j++) {
int t = 0;
while (s[k] != ' ' && s[k] != '\0') {
if (s[k] == 'x') {
t = -1;
}
else t = t * 10 + (s[k] - '0');
k++;
}k++;
A[i][j] = t;
A[j][i] = A[i][j];
if (j == 1) {
dist[i] = 0x3f3f3f3f;
}
}
}
dist[1] = 0;
Dijkstra(1);
int maxlen = 0;
for (int i = 1; i <= n; i++) {
maxlen = max(maxlen, dist[i]);
}
cout << maxlen << endl;
return 0;
}