• PTA 紧急救援 /// dijkstra 最短路数 输出路径


    题目大意:

    给定 n m s t ;表示n个点编号为0~n-1 m条边 起点s终点t

    接下来一行给定n个数;表示第i个点的救援队数量

    接下来m行给定u v w;表示点u到点v有一条长度为w的边

    求从s到t的最短路有几条

    一条路上可以集合的救援队最多有多少

    输出路径

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LL long long
    #define inc(i,j,k) for(int i=j;i<=k;i++)
    #define dec(i,j,k) for(int i=j;i>=k;i--)
    #define gcd(i,j) __gcd(i,j)
    #define mem(i,j) memset(i,j,sizeof(i))
    const int N=2e5+5;
    const int mod=1e9+7;
    
    int n,m,s,t;
    int V[N];
    struct NODE{ int to,len; };
    vector <NODE> G[N];
    int dis[N], num[N];
    int sumV[N], pre[N];
    bool vis[N];
    
    int main()
    {
        while(~scanf("%d%d%d%d",&n,&m,&s,&t)) {
            inc(i,0,n-1) scanf("%d",&V[i]);
            inc(i,0,n-1) G[i].clear();
            while(m--) {
                int u,v,w; scanf("%d%d%d",&u,&v,&w);
                G[u].push_back({v,w});
                G[v].push_back({u,w});
            }
            mem(sumV,0); sumV[s]=V[s]; // 到i点的最短路可集合sumV[i]救援队
            mem(dis,INF); dis[s]=0; // 到i点的最短路长度为dis[i]
            mem(num,0); num[s]=1; // 到i点的最短路有num[i]条
            mem(pre,-1); mem(vis,0); // pre记录路径前驱 vis标记走过
            while(1) {
                int u, mini=INF;
                inc(i,0,n-1)
                    if(!vis[i] && dis[i]<mini)
                        mini=dis[i], u=i;
                if(mini==INF) break; 
                vis[u]=1;
                int all=G[u].size();
                inc(i,0,all-1) {
                    NODE v=G[u][i];
                    if(vis[v.to]) continue;
                    if(dis[v.to]>dis[u]+v.len) {
                        sumV[v.to]=sumV[u]+V[v.to];
                        dis[v.to]=dis[u]+v.len;
                        num[v.to]=num[u];
                        pre[v.to]=u;
                    } else if(dis[v.to]==dis[u]+v.len) {
                        num[v.to]+=num[u];
                        if(sumV[v.to]<sumV[u]+V[v.to]) {
                            sumV[v.to]=sumV[u]+V[v.to],
                            pre[v.to]=u;
                        }
                    }
                }
            }
            printf("%d %d
    ",num[t],sumV[t]);
            stack <int> s; int c=0;
            while(t!=-1) s.push(t), t=pre[t], c++;
            while(!s.empty()) {
                printf("%d",s.top()); s.pop();
                if(--c==0) printf("
    ");
                else printf(" ");
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    做了个上传下载任意文件到数据库
    owc 的使用技巧
    设计模式
    WCF 附录 高级主题 系列文章
    .NET 3.5 中WCF客户端代理性能改进以及最佳实践
    WCF 的几个问题
    你了解 Assembly.Load 吗?
    WCF 第十三章 可编程站点 系列文章
    WCF 第十二章 对等网 系列文章
    最佳实践:显式打开共享访问的WCF客户端代理
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10571356.html
Copyright © 2020-2023  润新知