ccf 201903-5

 

 

题解:vector + 优先队列 -> 迪杰斯特拉算法

不必求任何两点的距离,只求行星据点到其余每个点的距离即可

把count个行星据点到其余每个点的距离存入二维数组

每一列就是对应顶点i到每个行星据点的最短距离,取出放入一维数组sort,然后取前k个即可,如果遇到INF则跳过不取

 

//迪杰斯特拉算法 (Vector + 优先队列)
#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>
#include <string.h>
#include <iostream>

#define MAX 10001
#define MAX_EDG 500001

using namespace std;

typedef pair<int, int> P;        //fisrt:dis[]  second:下标 
vector<P> map[MAX_EDG];      //用vector优化
priority_queue<P, vector<P>, greater<P> > q;
const int INF = 0x3f3f3f3f;

int d[MAX];
int vis[MAX];

int dis[MAX];
int flag[MAX];            //标志是否为行星据点 
int all[MAX][MAX];        //行星据点到其余顶点的最短距离 

void Dijkstra(int s, int count, int n){
    memset(dis,INF,sizeof(dis));     
    memset(vis,0,sizeof(vis));
    dis[s]=0;
    q.push(P(0,s));        //将起始点push入队列 
    while(!q.empty()){
        P p =q.top();
        q.pop();
        int u=p.second;
        if(vis[u])    continue;
        vis[u]=1;
        for(int i=0;i<map[u].size();i++){        //i并不是边的终点,只是顺序存储的东西 
            int v=map[u][i].second;                //边的终点v     
            int w=map[u][i].first;                //u到v的距离 
            if(!vis[v]){
                if(dis[v]>dis[u]+w){
                    dis[v]=dis[u]+w;
                    q.push(P(dis[v],v));
                }    
            }
        }
    }
    for(int i=1;i<=n;i++)    all[count][i]=dis[i];
}


int main(){
    int n,m,k;    
    int u,v,w; 
    int c,r,count;                                        //求S到其他点的最短路径上的权值和        
    while(scanf("%d %d %d",&n,&m,&k)!=EOF){        //N顶点数 M边数 S开始点 
        for(int i=1;i<=n;i++)
            map[i].clear();        //清空vector  注意 vector 不能用二维数组初始化    
        memset(flag,0,sizeof(flag));
        count=0;
        for(int i=1;i<=n;i++){
            cin >> flag[i];
            if(flag[i])        count++;
        }
        for(int i=1;i<=m;i++){
            scanf("%d %d %d",&u,&v,&w);
              map[u].push_back({w,v});        //无向图 
            map[v].push_back({w,u});        //有向图只push一次 
        }
        c=0;
           for(int i=1;i<=n;i++){
            if(flag[i]){                //求行星据点到每个顶点的距离,不必求任意两点之间的距离 
                Dijkstra(i, c, n);
                c++;
            }
        }
        for(int i=1;i<=n;i++){            //求n个顶点 
            memset(d,0,sizeof(d));        
            for(int j=0;j<count;j++)        //count个行星据点,count行 
                d[j] = all[j][i];        //顶点i到行星据点的距离等于对应的列的值 
            sort(d,d+count);
            r=0;
            for(int p=0;p<k; p++)
                if(d[p]!=INF)    r+=d[p];
            printf("%d\n",r);
        }
    }
    return 0;
}
posted @ 2020-01-11 13:31  北冥有鱼兮  阅读(131)  评论(0编辑  收藏  举报