• 1003 Emergency Dijkstra


    这题做的心很累,我用的还是 1018的思路做的,但是 使用dfs 求最大人数对于某些有问题(现在也不知道错哪了),

    看了别人的代码后才发现,其实完全不用这么麻烦,只需设置一个点的权重,一遍DJ(自创简称)下来,直接出答案

    收获:

    1.DJ不需要存储具体路径也能知道最短路径有几条:

    在DJ外设置一个road【n】数组,初始为0;road【源】=1;//road表示,从源出发,到n的最短路径条数

    在更新环节

    for()

    {

      if当dis[u] + e[u][v] < dis[v]

        road【v】=road【u】;

      else if当dis[u] + e[u][v] == dis[v]

        road【v】=road【v】+road【u】;    //通过U到V的路,加上不经过U到V的条数

    }//每个road【i】就是从源到i的最短路径条数了

    2.使用点权解决不需要输出路径的问题

    我在某大神的DJ算法中更新dis的部分看到了这样一句话

    for(int v = 0; v < n; v++) {//已经找到一个集合外的最小点 u,

                if(visit[v] == false && e[u][v] != inf) {   《-------这一句判断,不加这一句就是正常的思路,//对于既不是集合内的点,从U出发又不可达的点就跳过,感觉没有必要
                    if(dis[u] + e[u][v] < dis[v]) {      //因为这句判断本身已经要对所有输入都判断一次了
                        dis[v] = dis[u] + e[u][v];
                    }
                }

     
     
    我的部分正确代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<vector>
     4 using namespace std;
     5 const int inf=999999;
     6 int e[500][500];
     7 int man[500]={0};
     8 int N,M,C1=0,C2;
     9 int a,b,c;
    10 int num=0,most=0;//最短路径数,最大人数
    11 vector<int> pre[501];
    12 vector<int> path,tmppath;
    13 void dfs(int x)//由于存的是到达x的最短路径的前一个点,所以从后往前走C2起步
    14 {
    15   tmppath.push_back(x);
    16   if(x==C1)
    17   {
    18     num++;
    19     a=0;
    20     for(int i=tmppath.size()-1;i>=0;i--)//i初始化为路径上C1的下一个点
    21     {
    22       a+=man[i];
    23     }
    24     if(a>most)
    25     {
    26       path=tmppath;
    27       most=a;
    28     }
    29   }
    30   else
    31   {
    32     for(int i=0;i<pre[x].size();i++)
    33     {
    34       dfs(pre[x][i]);
    35     }
    36   }
    37   tmppath.pop_back();
    38 }
    39 
    40 
    41 
    42 
    43 int main()
    44 {
    45   scanf("%d%d%d%d",&N,&M,&C1,&C2);
    46   int dis[N];//DJ 距离
    47   int mark[N];//DJ 标记
    48   for(int i=0;i<N;i++)
    49   {
    50     for(int j=0;j<N;j++)
    51       e[i][j]=inf;
    52     dis[i]=inf;
    53     scanf("%d",&man[i]);
    54     mark[i]=0;
    55 
    56   }
    57   for(int i=0;i<M;i++)
    58   {
    59     scanf("%d%d%d",&a,&b,&c);
    60     e[a][b]=e[b][a]=c;
    61 
    62   }
    63   dis[C1]=0;//DJ初始化
    64   int now=C1,fast;
    65   for(int i=0;i<N;i++)//每次加入一个点
    66   {
    67     fast=inf;
    68     for(int j=0;j<N;j++)
    69     {
    70       if(dis[j]<fast&&mark[j]==0)//dis 小于当前发现的最小,并且没有被加入
    71       {
    72         now=j;
    73         fast=dis[j];
    74       }
    75     }
    76     if(fast==inf)break;//所有可达点都加入了
    77     mark[now]=1;//加入该点
    78     for(int j=0;j<N;j++)//用当前该点更新dis,并且更新pre
    79     {
    80       if(dis[now]+e[j][now]<dis[j])
    81       {
    82         dis[j]=dis[now]+e[j][now];
    83         pre[j].clear();
    84         pre[j].push_back(now);
    85       }
    86       else if(dis[now]+e[j][now]==dis[j])
    87       {
    88         pre[j].push_back(now);
    89       }
    90     }
    91   }//DJ 结束,dis[C2],为最短距离
    92   dfs(C2);//使用深搜 求出最短路径的条数 和 最大人数
    93   printf("%d %d",num,most);
    94 
    95   return 0;
    96 }
    mycode

     正确代码:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n, m, c1, c2;
    int e[510][510], weight[510], dis[510], num[510], w[510];
    bool visit[510];
    const int inf = 99999999;
    int main() {
        scanf("%d%d%d%d", &n, &m, &c1, &c2);
        for(int i = 0; i < n; i++)
            scanf("%d", &weight[i]);
        fill(e[0], e[0] + 510 * 510, inf);
        fill(dis, dis + 510, inf);
        int a, b, c;
        for(int i = 0; i < m; i++) {
            scanf("%d%d%d", &a, &b, &c);
            e[a][b] = e[b][a] = c;
        }
        dis[c1] = 0;
        w[c1] = weight[c1];
        num[c1] = 1;
        for(int i = 0; i < n; i++) {
            int u = -1, minn = inf;
            for(int j = 0; j < n; j++) {
                if(visit[j] == false && dis[j] < minn) {
                    u = j;
                    minn = dis[j];
                }
            }
            if(u == -1) break;
            visit[u] = true;
            for(int v = 0; v < n; v++) {
                if(visit[v] == false && e[u][v] != inf) {
                    if(dis[u] + e[u][v] < dis[v]) {
                        dis[v] = dis[u] + e[u][v];
                        num[v] = num[u];
                        w[v] = w[u] + weight[v];
                    } else if(dis[u] + e[u][v] == dis[v]) {
                        num[v] = num[v] + num[u];
                        if(w[u] + weight[v] > w[v])
                            w[v] = w[u] + weight[v];
                    }
                }
            }
        }
        printf("%d %d", num[c2], w[c2]);
        return 0;
    }
    right code
     
     
     
     
     
     
     
     
  • 相关阅读:
    JSP/Servlet开发——第二章 JSP数据交互(二)
    JSP/Servlet开发——第一章 动态网页基础
    Java OOP——第三章 多态
    Java OOP——第二章 继承
    Java OOP——第一章 对象和封装
    Java OOP——第四章 异常
    Linux 系统启动过程
    动画链接
    js判断浏览器类型
    localStorage封装
  • 原文地址:https://www.cnblogs.com/mgfsos/p/10582911.html
Copyright © 2020-2023  润新知