zoukankan      html  css  js  c++  java
  • hdu2066 一个人的旅行 最短路

    单源最短路裸题

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define min(a,b) (a)<(b)?a:b
     4 #define INF 100001
     5 int T,S,D,dist[1050],v[1050][1050],m,l[1050],r[1050];
     6 
     7 void DIJKSTRA(int x){
     8     int i,j,mi,minj;
     9     bool visit[1050]={0};
    10     for(i=1;i<=m;i++)dist[i]=v[x][i];
    11     visit[x]=1;
    12     for(i=1;i<m;i++){
    13         mi=INF;
    14         for(j=1;j<=m;j++){
    15             if(!visit[j]&&dist[j]<mi){
    16                 mi=dist[j];
    17                 minj=j;
    18             }
    19         }
    20         if(mi==INF) return;
    21         visit[minj]=1;
    22         for(j=0;j<=m;j++){
    23             if(!visit[j]&&dist[j]>dist[minj]+v[minj][j]){
    24                 dist[j]=dist[minj]+v[minj][j];
    25             }
    26         }
    27     }
    28 }
    29 
    30 
    31 int main(){
    32     while(scanf("%d%d%d",&T,&S,&D)!=EOF){
    33         int q,tm=0xFFFFFFF,i,j;
    34         for(i=1;i<1050;i++){
    35             for(j=1;j<1050;j++){
    36                 v[i][j]=INF;
    37             }
    38         }
    39         m=-1;
    40         for(q=1;q<=T;q++){
    41             int a,b,va;
    42             scanf("%d%d%d",&a,&b,&va);
    43             v[a][b]=v[b][a]=min(va,v[a][b]);
    44             if(a>m)m=a;
    45             if(b>m)m=b;
    46         }
    47         for(q=1;q<=S;q++)scanf("%d",&l[q]);
    48         for(q=1;q<=D;q++)scanf("%d",&r[q]);
    49         for(i=1;i<=S;i++){
    50             DIJKSTRA(l[i]);
    51             for(j=1;j<=D;j++){
    52                 if(dist[r[j]]<tm)tm=dist[r[j]];
    53             }
    54         }
    55         printf("%d
    ",tm);
    56     }
    57     return 0;
    58 }
    View Code

    以前不太懂,头硬直接跑了s遍没有优化的dijkstra,每遍循环看下d个点取最优也能过,复杂度应该是O( s * (n^2) ),那么大概s不是很大,所以据说O(n^3)的floyd过不了(据说,我也不清楚),但是这样都能过。

    不过现在重新看,这个题对于初学者来说应该还是很有亮点的。

    它的s个起点、d个终点可以为其建立一个源点一个汇点,这样源点有条边到每个可行起点,而每个可行终点有条边到汇点,只需要从源点到汇点跑一次单源最短路,无需遍历终点直接输出汇点的dis就是答案了。

    这种题当时要是没有水过去,而是被卡了找找网上的分析,应该很有帮助吧。

     1 #include<stdio.h>        //基本需要的头文件
     2 #include<string.h>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 const int INF=0x3f3f3f3f;
     7 
     8 const int maxn=1e3+5;
     9 const int maxm=1e5+5;
    10 
    11 struct pii{
    12     int dis;
    13     int s;
    14     bool operator < (const pii x)const{
    15         return dis > x.dis;
    16     }
    17     pii(int a,int b):dis(a),s(b){};
    18 };
    19 int head[maxn],nxt[maxm<<1],val[maxm<<1],point[maxm<<1],size;
    20 int dis[maxn];
    21 
    22 void init(){
    23     memset(head,-1,sizeof(head));
    24     size=0;
    25 }
    26 
    27 void add(int a,int b,int v){
    28     point[size]=b;
    29     val[size]=v;
    30     nxt[size]=head[a];
    31     head[a]=size++;
    32 }
    33 
    34 void dij(int s,int t){            //传入出发点和到达点
    35     int i;
    36     priority_queue<pii>q;
    37     q.push(pii(0,s));
    38     memset(dis,0x3f,sizeof(dis));
    39     dis[s]=0;
    40     while(!q.empty()){
    41         pii u=q.top();
    42         q.pop();
    43         if(u.dis>dis[u.s])continue;
    44         for(i=head[u.s];~i;i=nxt[i]){
    45             int j=point[i];
    46             if(dis[j]>u.dis+val[i]){
    47                 dis[j]=u.dis+val[i];
    48                 q.push(pii(dis[j],j));
    49             }
    50         }
    51     }
    52     printf("%d
    ",dis[t]);        //或去掉在主函数中输出或操作
    53 }
    54 
    55 int main(){
    56     int t,s,d;
    57     while(scanf("%d%d%d",&t,&s,&d)!=EOF){
    58         init();
    59         while(t--){
    60             int a,b,v;
    61             scanf("%d%d%d",&a,&b,&v);
    62             add(a,b,v);
    63             add(b,a,v);
    64         }
    65         for(int i = 1 ; i <= s ; ++ i){
    66             int a;
    67             scanf("%d",&a);
    68             add(0,a,0);
    69         }
    70         for(int i = 1 ; i <= d ; ++ i){
    71             int a;
    72             scanf("%d",&a);
    73             add(a,1001,0);
    74         }
    75         dij(0,1001);
    76     }
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    C#--SQL server数据库基本操作(增、删、改、查)
    《linux就该这么学》课堂笔记05 管道符、通配符、转义、vim编辑器
    《linux就该这么学》课堂笔记04 常用命令cat、mor...tar、find
    《linux就该这么学》课堂笔记03 命令初识 echo、date、reboot、poweroff、wget...
    《linux就该这么学》课堂笔记02 虚拟机安装使用
    《Linux就该这么学》课堂笔记01 linux初识
    paramiko
    restframework详细
    部署你的CRM程序
    nginx+uWSGI+django+virtualenv+supervisor发布web服务器
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/6577973.html
Copyright © 2011-2022 走看看