MPI Maelstrom dijkstra

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 access and communication times are not uniform,'' Valentine told Swigert. ``Communication is fast between processors that share the same memory subsystem, but it is slower between processors that are not on the same subsystem. Communication between the Apollo and machines in our lab is slower yet.'' 

``How is Apollo's port of the Message Passing Interface (MPI) working out?'' Swigert asked. 

``Not so well,'' Valentine replied. ``To do a broadcast of a message from one processor to all the other n-1 processors, they just do a sequence of n-1 sends. That really serializes things and kills the performance.'' 

``Is there anything you can do to fix that?'' 

``Yes,'' smiled Valentine. ``There is. Once the first processor has sent the message to another, those two can then send messages to two other hosts at the same time. Then there will be four hosts that can send, and so on.'' 

``Ah, so you can do the broadcast as a binary tree!'' 

``Not really a binary tree -- there are some particular features of our network that we should exploit. The interface cards we have allow each processor to simultaneously send messages to any number of the other processors connected to it. However, the messages don't necessarily arrive at the destinations at the same time -- there is a communication cost involved. In general, we need to take into account the communication costs for each link in our network topologies and plan accordingly to minimize the total time required to do a broadcast.''

Input

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.

Output

Your program should output the minimum communication time required to broadcast a message from the first processor to all the other processors.

Sample Input

 

5
50
30 5
100 20 50
10 x x 10

Sample Output

35

题意:

0

50   0

30     5    0

100   20     50    0

10     x       x       10     0

一个矩阵,求第一个点将消息传与其他点的最小时间,也就是求第一个点到其他点的距离(最小距离),压缩过后的最大距离;

Prim算法和Dijkstra算法十分相似,惟一的区别是:  Prim算法要寻找的是离已加入顶点距离最近的顶点;
Dijkstra算法是寻找离固定顶点距离最近的顶点。

代码:(没有提交,没有多组输入输出)

#include<iostream>
#include<cstring>
# define M 9999999
using namespace std;
int d[999];
int p[999];
int n;
int map[999][999];
 int find(char *s)  //赋值
    {  
        if(s[0]=='x')  
        {  
            return M;  
        }  
        int sum = 0;  
        for(int i=0;i<strlen(s);i++)  
        {  
            sum = sum * 10 + s[i] - '0';  
        }  
        return sum;  
    }  
void dijkstra(int n)
{
    for(int i=1;i<=n;i++)
    {
        d[i]=map[1][i];
    }
    p[1]=1;
    while(1)
    {
        int min=M,u=-1;
        for(int i=1;i<=n;i++)
        {
            if(min>d[i]&&!p[i])
            {
                min=d[i];
                u=i;
            }
        }
        if(u==-1)
        break;
        p[u]=1;
        for(int i=1;i<=n;i++)
        {
            if(map[u][i]!=M&&d[i]>d[u]+map[u][i])
            {
                 d[i]=d[u]+map[u][i];
            }
        }
    }
}
int main()
{
    cin>>n;
    memset(p,0,sizeof(p));
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<i;j++)
        {
            char ch[5];
            cin>>ch;
            if(ch[0]=='x')
            {
             map[i][j]=M;
            }
            else
            {
                map[i][j]=find(ch);
            }
        
            map[j][i]=map[i][j];
        }  
        
    }
        dijkstra(n);
        int ans = 0;  
        for(int i=1;i<=n;i++)  
        {  
            ans = max(ans,d[i]);  
        }  
        printf("%d\n",ans);  
}

 

你来到一个迷宫前。该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数。还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间。游戏规定了你的起点和终点房间,你首要目标是从起点尽快到达终点,在满足首要目标的前提下,使得你的得分总和尽可能大。现在问题来了,给定房间、道路、分数、起点和终点等全部信息,你能计算在尽快离开迷宫的前提下,你的最大得分是多少么?

 

输入

 

第一行4个整数n (<=500), m, start, end。n表示房间的个数,房间编号从0到(n - 1),m表示道路数,任意两个房间之间最多只有一条道路,start和end表示起点和终点房间的编号。
第二行包含n个空格分隔的正整数(不超过600),表示进入每个房间你的得分。
再接下来m行,每行3个空格分隔的整数x, y, z (0<z<=200)表示道路,表示从房间x到房间y(双向)的道路,注意,最多只有一条道路连结两个房间, 你需要的时间为z。
输入保证从start到end至少有一条路径。

 

输出

 

一行,两个空格分隔的整数,第一个表示你最少需要的时间,第二个表示你在最少时间前提下可以获得的最大得分。

 

输入示例

 

3 2 0 2
1 2 3
0 1 10
1 2 11


输出示例

 

21 6 代码1:
  1. #include<stdio.h>  
  2. #include<algorithm>  
  3. #include<iostream>  
  4. #include<string.h>  
  5. #define INF 0x3f3f3f  
  6. using namespace std;  
  7. int map[505][505],v[505],dis[505],n,m,end,stare,score[505],ans[505];  
  8. void Dij(int x)  
  9. {  
  10.     ans[x]=score[x];//ans[i]记录从起始点到i所获的得分  
  11.     memset(v, 0, sizeof(v));  
  12.     for (int i = 0; i < n; ++i)  
  13.     {  
  14.         if (map[x][i] < INF)  
  15.             ans[i] = ans[x] +score[i];//更新得分  
  16.         dis[i] = map[x][i];  
  17.     }  
  18.     dis[x] = 0;  
  19.     v[x] = 1;  
  20.     for (int i = 1; i < n; ++i)  
  21.     {  
  22.         int u = 0, min = INF;  
  23.         for (int j = 0; j < n; ++j)  
  24.         {  
  25.             if (!v[j] && dis[j] < min)  
  26.             {  
  27.                 min = dis[j];  
  28.                 u = j;  
  29.             }  
  30.         }  
  31.         v[u] = 1;  
  32.         for (int k = 0; k < n; ++k)  
  33.         {  
  34.             if (!v[k] && dis[k] > map[u][k] + dis[u])  
  35.             {  
  36.                 dis[k] = map[u][k] + dis[u];  
  37.                 ans[k] = ans[u] + score[k];  
  38.             }  
  39.         }  
  40.         for (int k = 0; k < n; ++k)  
  41.         {  
  42.             if (dis[k] == map[u][k] + dis[u])  
  43.                 ans[k] = max(ans[k], ans[u] + score[k]);//若路程相同,找出得分最大的  
  44.         }  
  45.     }  
  46.     printf("%d %d\n", dis[end], ans[end]);  
  47. }     
  48. int main()  
  49. {int x,y,z;  
  50. scanf("%d%d%d%d",&n,&m,&stare,&end);  
  51. for(int i=0;i<=n;i++)  
  52. for(int j=0;j<=n;j++)  
  53. {  
  54. map[i][j]=INF;  
  55. }  
  56. for(int i=0;i<n;i++)  
  57. scanf("%d",&score[i]);  
  58. for(int i=1;i<=m;i++)  
  59. {  
  60. scanf("%d%d%d",&x,&y,&z);  
  61. map[x][y]=map[y][x]=z;}  
  62. Dij(stare);  

代码·:SPEFA:

    #include<iostream>  
    #include<algorithm>  
    #include<cstring>  
    #include<queue>  
    #include<map>  
    #include<cmath>  
    #include<cstdio>  
    #define LL long long  
    using namespace std;  
    const int MAXN=1000010;  
    const int INF=0x3f3f3f3f;  
    struct node{  
        int to;  
        int w;  
        int next;  
    }edge[MAXN];  
    int point[MAXN];  
    int st,ed,n,m;  
    int tot=0;  
    int head[MAXN];  
    bool vis[MAXN];//vis[i]=true表示的是点i在队列中 vis[i]=false表示不在队列中  
    int dis[MAXN];  
    int sco[MAXN];  
    int cnt[MAXN];//统计顶点的入队次数  
    void init()  
    {  
        memset(head,-1,sizeof(head));  
        memset(vis,false,sizeof(vis));  
        tot=0;  
    }  
    void add(int u,int v,int w)  
    {  
        edge[tot].to=v;  
        edge[tot].w=w;  
        edge[tot].next=head[u];  
        head[u]=tot++;  
    }  
    bool spfa(int st,int ed)  
    {  
        deque<int>q;  
        int now,nex,i;  
        for(int i=0;i<n;i++)  
        {  
            vis[i]=false;  
            cnt[i]=0;  
            dis[i]=INF;  
            sco[i]=point[i];  
        }  
        dis[st]=0;  
        sco[st]=point[st];  
        q.push_back(st);  
        vis[st]=true;//注意:这里跟广搜不同,vis[i]=true表示的是点i在队列中 vis[i]=false表示不在队列中,  
        cnt[st]++;   //并不是像广搜那样一旦标记访问过后就不能再访问的意思!!!   
        while(!q.empty())  
        {  
            now=q.front();  
            q.pop_front();//队头元素出队,并且消除标记  
            vis[now]=false;//广搜没有这句!!!spfa用这句是为了后面回溯到图中的某个交叉点后  
            if(cnt[now]>n)//向另一个方向(另一个方向的点不在队列中)搜索,这样子的广搜类似深搜的回溯操作   
            {  
                return false; //超过入队次数上限,说明有负环  
            }  
            for(i=head[now];i!=-1;i=edge[i].next)  
            {  
                nex=edge[i].to;  
                if(dis[nex]>dis[now]+edge[i].w)  
                {  
                    dis[nex]=dis[now]+edge[i].w;  
                    sco[nex]=point[nex]+sco[now];  
                    if(!vis[nex]) //顶点不在队内  
                    {  
                        vis[nex]=true;  
                        cnt[nex]++;  
                        if(!q.empty()&&dis[nex]<dis[q.front()])  
                        {  
                            q.push_front(nex);  
                        }  
                        else  
                        {  
                            q.push_back(nex);  
                        }  
                    }  
                }  
                else if(dis[nex]==dis[now]+edge[i].w&&sco[nex]<point[nex]+sco[now])  
                {  
                    sco[nex]=point[nex]+sco[now];  
                    if(!vis[nex])  
                    {  
                        cnt[nex]++;  
                        vis[nex]=true;  
                        if(!q.empty()&&dis[nex]<dis[q.front()])  
                        {  
                            q.push_front(nex);  
                        }  
                        else  
                        {  
                            q.push_back(nex);  
                        }  
                    }  
                }  
            }  
        }  
        return true;  
    }  
    int main()  
    {  
        int i,u,v,w;  
        //freopen("D:\p1459t5in.txt","r",stdin);  
        while(scanf("%d%d%d%d",&n,&m,&st,&ed)!=EOF)  
        {  
            for(i=0;i<n;i++)  
            {  
                scanf("%d",&point[i]);  
            }  
            init();  
            while(m--)  
            {  
                scanf("%d%d%d",&u,&v,&w);  
                add(u,v,w);  
                add(v,u,w);  
            }  
            spfa(st,ed);  
            printf("%d %d\n",dis[ed],sco[ed]);  
        }  
        return 0;  
    } 
 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值