hduoj 2066 最短路径 + 离散化节点 djkstra

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>

#define MAXN 1000+5
#define INF  (int)1e9+5
#define DEBUG 1

using namespace std;

//int G[MAXN][MAXN] = {INF};        //图
//int COST[MAXN][MAXN] = {0};     //代价
int N=0,M;

int cost_d[MAXN] = {INF};       //距离数组
int cost_p[MAXN] = {0};         //花费数组
int vis[MAXN]={0};

struct Edge{

    int u,v,d;
    int uu,vv;//uu vv代表离散化后的节点序号

};

vector<Edge> vec_edges;
vector<int> Nodes;
vector<int> vec_Start;//存储相邻的城市
vector<int> vec_endd;//存储想去的地方
int T,S,D;  //T代表边数,S代表有几个城市,D代表要去的几个地方

//vector 存储节点
/*
void init(){
    memset(G,INF,sizeof(G));
    memset(cost_d,INF,sizeof(cost_d));
    memset(vis,0,sizeof(vis));
    N=0;
    vec_Start.clear();
    vec_endd.clear();
}

void solve(){
    int a,b,d;

    while(scanf("%d %d %d",&T,&S,&D)==3){
        init();
        //先将边输入进来
        for(int i=0;i<T;i++){

            scanf("%d%d%d",&a,&b,&d);
            Edge edge;
            edge.u = a;
            edge.v =b;
            edge.d = d;
            if(edge.d<G[a][b])
                G[a][b] = G[b][a] = d;
            N= max(max(a,b),N);
        }
        for(int i=0;i<S;i++){
            int t1;
            scanf("%d",&t1);
            vec_Start.push_back(t1);
            vis[t1] = 1;
            cost_d[t1] = 0;
        }
        for(int i=0;i<D;i++){
            int t1;
            scanf("%d",&t1);
            vec_endd.push_back(t1);
        }

        //首先将起始点初始化  即cost-d数组第一次
        for(int i=1;i<=N;i++){
            if(vis[i])
                continue;
            for(int j=0;j<vec_Start.size();j++){
                if(G[vec_Start[j]][i]){
                    if(cost_d[i] >G[vec_Start[j]][i]){
                        cost_d[i] = G[vec_Start[j]][i];
                    }
                }
            }
        }

        //遍历剩下的节点
        for(int i=1;i<N;i++){
            if(vis[i]){
                continue;
            }
            int next;
            int minn = INF;
            //查找最小的路径
            for(int i=1;i<=N;i++){
                if(!vis[i] && cost_d[i] <minn){
                    next = i;
                    minn = cost_d[i];
                }
            }

            vis[next] = 1;
            //到达其他节点
            for(int i =1;i<=N;i++){
                if(!vis[i]&&G[next][i]<INF){
                    if(G[next][i] +cost_d[next] < cost_d[i]){
                        cost_d[i] = G[next][i] +cost_d[next];
                    }

                }

            }

        }

        int minn = INF,mark;
        for(int i=0;i<vec_endd.size();i++){
            if(minn > cost_d[vec_endd[i]]){
                mark = vec_endd[i];
                minn = cost_d[vec_endd[i]];
            }
        }

        cout<<minn<<endl;
    }



}
*/
vector<vector<Edge> > G(MAXN);
//在加上离散化

int search_node(int value,int Size){
    int l =0,r = Size;

    while(l>r){

        int mid = (l+r)>>1;
        if(Nodes[mid] == value)
            return mid;
        else if(Nodes[mid] < value){
            l = mid +1;
        }else{
            r = mid-1;
        }
    }
    return -1;

}

void init1(){
    //memset(G,INF,sizeof(G));
    memset(cost_d,INF,sizeof(cost_d));
    memset(vis,0,sizeof(vis));
    for(int i=0;i<MAXN;i++){
        G[i].clear();
    }
    N=0;
    vec_Start.clear();
    vec_endd.clear();
    Nodes.clear();
}


void solve1(){
    int a,b,d;

    while(scanf("%d %d %d",&T,&S,&D)==3){
        init1();
        //先将边输入进来
        for(int i=0;i<T;i++){

            scanf("%d%d%d",&a,&b,&d);
            Edge edge;
            edge.u = a;
            edge.v =b;
            edge.d = d;
            vec_edges.push_back(edge);
            //离散化前先存入节点vec中
            Nodes.push_back(a);
            Nodes.push_back(b);
            N= max(max(a,b),N);
        }


        //离散化   sort 最后一位是不取的
        sort(Nodes.begin(),Nodes.end());
        int Node_Size = unique(Nodes.begin(),Nodes.end()) - Nodes.begin();
        //离散化后对应的可能为
        //前   2 4 6 8 9
        //后   0 1 2 3 4

        G.resize(Node_Size);
        for(int i=0;i<G.size();i++)
            G[i].resize(Node_Size + 1000);


        //将各节点离散化的顺序对应起来
        //并将各边存储进图中
        for(int i=0;i<T;i++){
            Edge& edge = vec_edges[i];
            int uu = search_node(edge.u,Node_Size);
            int vv = search_node(edge.v,Node_Size);
            edge.uu = uu;
            edge.vv = vv;
            G[uu].push_back(edge);
            G[vv].push_back(edge);
        }

        //合并起点
        for(int i=0;i<S;i++){
            //t1是原始的节点顺序,
            int t1;
            scanf("%d",&t1);
            int index = search_node(t1,Node_Size);
            vec_Start.push_back(index);
            //找到离散化后的节点
            //

            vis[index] = 1;
            cost_d[index] = 0;
        }
        for(int i=0;i<D;i++){
            int t1;
            scanf("%d",&t1);
            int index = search_node(t1,Node_Size);
            vec_endd.push_back(index);
        }

        //首先将起点初始化
        //并将起始点到所有能到达的点的坐标一一更新
        for(int i = 0;i<vec_Start.size();i++){
            int u = vec_Start[i];
            for(int j =0;j<G[u].size();j++){
                Edge& edge = G[u][j];
                int v = (u==edge.uu? edge.vv:edge.uu);
                if(vis[v])
                    continue;
                if(edge.d < cost_d[v]){
                    cost_d[v] = edge.d;
                }
            }

        }

        //遍历剩下的节点
        for(int i=0;i<Node_Size;i++){
            if(vis[i])
                continue;
            int next;
            int minn = INF;

            //从cost_d中寻找最短的路径
            for(int j=0;j<Node_Size;j++){
                if(!vis[j]&& minn >cost_d[j]){
                    next = j;
                    minn = cost_d[j];
                }
            }
            vis[next] =1;

            //从next节点访问剩下的节点
            for(int j=0;j<G[next].size();j++){
                Edge& edge = G[next][j];
                int v = (next==edge.uu? edge.vv:edge.uu);
                if(vis[v])
                    continue;
                if(edge.d + cost_d[next] < cost_d[v]){
                    cost_d[v] = edge.d+cost_d[next];
                }
            }

        }




        int minn = INF,mark;
        for(int i=0;i<vec_endd.size();i++){
            int v = vec_endd[i];
            int vv = search_node(v,Node_Size);
            if(minn > cost_d[vv]){
                mark = vv;
                minn = cost_d[vv];
            }
        }

        cout<<minn<<endl;
    }




}

int main()
{
    if(DEBUG)
        freopen("data.txt","r",stdin);

    solve1();
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值