zoukankan      html  css  js  c++  java
  • 训练指南 UVALive


    layout: post
    title: 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)
    author: "luowentaoaa"
    catalog: true
    mathjax: true
    tags:
    - Dijkstra
    - 最短路树
    - 图论
    - 训练指南


    Warfare And Logistics

    UVALive - 4080

    题意

    ①先求任意两点间的最短路径累加和,其中不连通的边权为L ②删除任意一条边,求全局最短路径和的最大值

    题解

    刚看到题目是让各点之间的最短路径和,所以立马想到啦floyd算法求最短路,然后发现还要去掉一条边后求最短路中的最大值,则floyd会超时,所以打算用dijkstra+堆优化做,首先枚举n个顶点求各个顶点之间的最短路径,并求出最短路树,然后枚举每条边,如果这条边在最短路树中,则再求一遍该点的最短路径即可,如果不在最短路树中,则直接利用第一次求得最短路即可。

    所谓的最短路树是指在求最短路的同时,记录最短路径并且标记那些点之间的连线有用到。

    如果在枚举某个作为起点的时候这删去的点没有用到那就直接加上答案即可,这样时间就省去了一个m

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=100+10;
    const int inf=1000000000;
    struct Edge{
        int from,to,dist;
    };
    struct HeapNode{
        int d,u;
        bool operator <(const HeapNode& rhs)const{
            return d>rhs.d;
        }
    };
    struct Dijkstra{
        int n,m;              ///点数和边数  点编号0~N-1
        vector<Edge>edges;    ///边列表
        vector<int>G[maxn];   ///每个节点出发的边编号
        bool done[maxn];      /// 是否已永久标号
        int d[maxn];          /// s到各个点的距离
        int p[maxn];          /// 最短路中的上一条边
    
        void init(int n){
            this->n=n;
            for(int i=0;i<n;i++)G[i].clear();
            edges.clear();
        }
        void AddEdge(int from,int to,int dist){ ///无向图调用两次
            edges.push_back((Edge){from,to,dist});
            m=edges.size();
            G[from].push_back(m-1);
        }
        void dijkstra(int s){
            priority_queue<HeapNode>Q;
            for(int i=0;i<n;i++)d[i]=inf;
            d[s]=0;
            memset(done,0,sizeof(done));
            Q.push((HeapNode){0,s});
            while(!Q.empty()){
                HeapNode x=Q.top();Q.pop();
                int u=x.u;
                if(done[u])continue;
                done[u]=true;
                for(int i=0;i<G[u].size();i++){
                    Edge& e=edges[G[u][i]];
                    if(e.dist>0&&d[e.to]>d[u]+e.dist){
                        d[e.to]=d[u]+e.dist;
                        p[e.to]=G[u][i];
                        Q.push((HeapNode){d[e.to],e.to});
                    }
                }
            }
        }
    };
    
    Dijkstra solver;
    int n,m,L;
    vector<int>gr[maxn][maxn];
    int used[maxn][maxn][maxn];
    int idx[maxn][maxn];
    int sum_single[maxn];
    
    int compute_c(){
        int ans=0;
        memset(used,0,sizeof(used));
        for(int src=0;src<n;src++){
            solver.dijkstra(src);
            sum_single[src]=0;
            for(int i=0;i<n;i++){
                if(i!=src){
                    int fa=solver.edges[solver.p[i]].from;
                    used[src][fa][i]=used[src][i][fa]=1;
                }
                sum_single[src]+=(solver.d[i]==inf?L:solver.d[i]);
            }
            ans+=sum_single[src];
        }
        return ans;
    }
    int compute_newc(int a,int b){
        int ans=0;
        for(int src=0;src<n;src++)
            if(!used[src][a][b])ans+=sum_single[src];
            else{
                solver.dijkstra(src);
                for(int i=0;i<n;i++)
                    ans+=(solver.d[i]==inf?L:solver.d[i]);
            }
        return ans;
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        while(cin>>n>>m>>L){
            solver.init(n);
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)gr[i][j].clear();
            for(int i=0;i<m;i++){
                int a,b,s;
                cin>>a>>b>>s;a--;b--;
                gr[a][b].push_back(s);
                gr[b][a].push_back(s);
            }
            for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)if(!gr[i][j].empty()){
                sort(gr[i][j].begin(),gr[i][j].end());
                solver.AddEdge(i,j,gr[i][j][0]);
                idx[i][j]=solver.m-1;
                solver.AddEdge(j,i,gr[i][j][0]);
                idx[j][i]=solver.m-1;
            }
            int c=compute_c();
            int c2=-1;
            for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)if(!gr[i][j].empty()){
                int &e1=solver.edges[idx[i][j]].dist;
                int &e2=solver.edges[idx[j][i]].dist;
                if(gr[i][j].size()==1)e1=e2=-1;
                else e1=e2=gr[i][j][1];
                c2=max(c2,compute_newc(i,j));
                e1=e2=gr[i][j][0];
            }
            cout<<c<<" "<<c2<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    苹果一体机发射Wi-Fi
    iphone 屏蔽系统自动更新,消除设置上的小红点
    data parameter is nil 异常处理
    copy与mutableCopy的区别总结
    java axis2 webservice
    mysql 远程 ip访问
    mysql 存储过程小问题
    mysql游标错误
    is not writable or has an invalid setter method错误的解决
    Struts2中关于"There is no Action mapped for namespace / and action name"的总结
  • 原文地址:https://www.cnblogs.com/luowentao/p/10347356.html
Copyright © 2011-2022 走看看