uva 1416 - Warfare And Logistics(dijkstra)

The army of United Nations launched a new wave of air strikes on terrorist forces. The objective of the mission is to reduce enemy's logistical mobility. Each air strike will destroy a path and therefore increase the shipping cost of the shortest path between two enemy locations. The maximal damage is always desirable.

Let's assume that there are n enemy locations connected bym bidirectional paths, each with specific shipping cost. Enemy's total shipping cost is given asc = $ \sum^{​{n}}_{​{i=1}}$$ \sum^{​{n}}_{​{j=1}}$path(i,j) . Here path(i, j) is the shortest path between locationsi and j . In casei and j are not connected,path(i, j) = L . Each air strike can only destroy one path. The total shipping cost after the strike is noted asc' . In order to maximized the damage to the enemy, UN's air force try to find the maximalc' - c .

Input

The first line ofeach input case consists ofthree integers: n , m , and L . 1 < n$ \le$100 ,1$ \le$m$ \le$1000 , 1$ \le$L$ \le$10$\scriptstyle \wedge$8 . Each ofthe following m lines contains three integers:a , b , s , indicating length of the path between a andb .

Output

For each case, output the total shipping cost before the air strike and the maximal total shipping cost after the strike. Output them in one line separated by a space.

Sample Input

4  6  1000
1  3  2
1  4  4
2  1  3
2  3  3
3  4  1
4  2  2

Sample Output

28  38

这题过的真艰辛!从昨晚搞到现在,最后写个数据生成程序+别人ac的代码,生成了点数据才发现错在哪儿了
本题关键就是记录下每条边是属于哪些棵生成树,然后删边后重新计算相应的变化。
但是,如果开始时就没有一颗最短路的生成树(即图不连通),那我们就需要特别注意了(我就是wa在这个地方被搞死了啊)
开始时还犯了个sb错误,把边的最大数目搞错了(导致数组开小,无限re)
因为是无向图,所以用模版加边时每条边加了两次,所以最后总边数是乘以2了的
还有如果数据给出了一条类似a->a的边,输入应该直接跳过

关于这道题还有一个拓展:
假如这道题改为如果之后输入m条边,要求计算添加了某条边的最小值。
当然还是可以用本题的方法去做,但实际上面对这个问题还有一个更好的方法。
如果你深入理解了floyed这个动态规划的算法,在面对这个题其实也是可以应用的。
也是抓住影响的只有与改变的那条边相关的最短路。
首先Floyd求出任意两点间的最短距离,之后关键是每更新一条边该如何维护这些最短距离。
假设用floyd求出来后的答案存在矩阵map[n][n]里,对于每次更新(a[i][j]=k),如果a[i][j]>=map[i][j],则不用更新;
否则,对于map[x][y],需要更新的只有两种情况,一种是从x->i->j->y,另一种是x->j->i->y,选出这两种的最小的与当前的map[x][y]比较即可。
因此只需要枚举x,y,然后更新map[x][y],总复杂度为O(n^3+m*n^2),比用dijkstra要好一些

floyed不能用在本题的原因是,原来的边被删掉,而导致边长变大,这样是无法处理的。

代码如下:

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn = 100 + 5;
const int INF = 1000000000;

struct Edge{
    int from,to;
    LL dist;
    int tag;//XiuGai
};

struct Heapnode{//优先队列的结点
    int d,u;
    bool operator < (const Heapnode& rhs) const{
        return d > rhs.d;
    }
};

struct Dijkstra{
    int n,m;//点数和边数
    vector<Edge> edges;//边列表
    vector<int> G[maxn];//每个节点出发的边编号(从0开始)
    bool done[maxn];//是否已永久编号
    int d[maxn];//s到各个点的距离
    int p[maxn];//最短路中的上一条边
    vector<int> mark[2005];
    LL l;

    void init(int n,LL l){
        this->n = n;
        for(int i = 0;i < n;i++) G[i].clear();//清空邻接表
        edges.clear();//清空边表

        for(int i = 0;i < 1005;i++) mark[i].clear();
        for(int i = 0;i < maxn;i++) p[i] = -1;
        this->l = l;
    }

    void AddEdge(int from,int to,LL dist,int tag){
        //如果是无向图,每条无向边需调用两次AddEdge
        edges.push_back((Edge){from,to,dist,tag});
        m = edges.size();
        G[from].push_back(m-1);//(m-1)因为边从0开始编号
    }

    LL dijkstra(int s){//求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.tag == 0) continue;//XiuGai
                if(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});
                }
            }
        }

        LL ret = 0;
        for(int i = 0;i < n;i++){
            if(i == s)  continue;
            if(d[i] == INF) ret += l;
            else ret += d[i];
        }
        return ret;
    }

    void track(int s){
        for(int i = 0;i < n;i++){
            if(i == s)  continue;
            if(p[i] == -1)  continue;
            mark[p[i]].push_back(s);
        }
    }

    void fuckedge(int n){
        edges[n].tag = 0;
        if(edges[n].from == edges[n+1].to && edges[n].dist == edges[n+1].dist && edges[n].to == edges[n+1].from)
            edges[n+1].tag = 0;
        else
            edges[n-1].tag = 0;
    }

    void recover(int n){
        edges[n].tag = 1;
        if(edges[n].from == edges[n+1].to && edges[n].dist == edges[n+1].dist && edges[n].to == edges[n+1].from)
            edges[n+1].tag = 1;
        else
            edges[n-1].tag = 1;
    }
};

Dijkstra solver;
LL ans[maxn];
LL c,c2;

int main(){
    //freopen("a","r",stdin);
    //freopen("A1","w",stdout);
    int n,m,l;
    int a,b,s;

    while(scanf("%d%d%d",&n,&m,&l) != EOF){
        solver.init(n,l);
        c = 0;
        while(m--){
            scanf("%d%d%d",&a,&b,&s);a--;b--;
            if(a == b)  continue;
            solver.AddEdge(a,b,s,1);solver.AddEdge(b,a,s,1);
        }
        for(int i = 0;i < n;i++){
            c += ans[i] = solver.dijkstra(i);
            solver.track(i);
        }
        c2 = c;LL tem;
        for(int i = 0;i < solver.edges.size();i++){
            solver.fuckedge(i);
            if(i%2==0) tem = c;
            for(int j = 0;j < solver.mark[i].size();j++){
                tem -= ans[solver.mark[i][j]];
                tem += solver.dijkstra(solver.mark[i][j]);
            }
            solver.recover(i);
            c2 = max(c2,tem);
        }
        printf("%lld %lld\n",c,c2);
    }
    return 0;
}

生成数据

#include <cstdio>
#include <cstdlib>
#include <time.h>

int main(){
    srand((int)time(NULL));
    freopen("a","w",stdout);
    for(int i = 0;i < 5;i++){
        int n,m;
        printf("%d %d %d\n",n = rand()%5+2,m = rand()%10+1,rand()%1000000);
        while(m--){
            printf("%d %d %d\n",rand()%n+1,rand()%n+1,rand()%10000);
        }
        printf("\n\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本项目是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。该系统主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者,包含项目源码、数据库脚本、项目说明等,有论文参考,可以直接作为毕设使用。 后台框架采用SpringBoot,数据库使用MySQL,开发环境为JDK、IDEA、Tomcat。项目经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。 该系统的功能主要包括商品管理、订单管理、用户管理等模块。在商品管理模块中,可以添加、修改、删除商品信息;在订单管理模块中,可以查看订单详情、处理订单状态;在用户管理模块中,可以注册、登录、修改个人信息等。此外,系统还提供了数据统计功能,可以对销售数据进行统计和分析。 技术实现方面,前端采用Vue框架进行开发,后端使用SpringBoot框架搭建服务端应用。数据库采用MySQL进行数据存储和管理。整个系统通过前后端分离的方式实现,提高了系统的可维护性和可扩展性。同时,系统还采用了一些流行的技术和工具,如MyBatis、JPA等进行数据访问和操作,以及Maven进行项目管理和构建。 总之,本系统是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。系统经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。
### 回答1: 《电子战与雷达系统工程手册》第四版是一本非常重要的参考书籍,该手册覆盖了广泛的主题,包括雷达技术、电子战、信号处理、通信、导航和控制等。这本手册可以作为电子工程师、雷达系统工程师以及电子战专家的参考书,也可以作为大学物理、电子工程和电信工程等专业的教材。 该手册的第四版主要涵盖了最新的雷达和电子战技术,还加入了一些新的章节,例如网络中的雷达和电子战、集成电子战系统和科学研究等。此外,该手册还包括了大量的实际应用例子和案例研究,这些例子可以被用来指导读者如何应用理论知识来设计和实现雷达和电子战系统。 总的来说,《电子战与雷达系统工程手册》第四版是一本非常实用的参考书籍,可以帮助读者快速掌握最新的雷达和电子战技术,同时也可以帮助读者深入了解这些技术的理论与应用,这将对电子工程师、雷达系统工程师、电子战专家以及大学物理、电子工程和电信工程等专业的学生们有很大的帮助。 ### 回答2: “Electronic Warfare and Radar Systems Engineering Handbook. 4th edition” 是一本工程手册,主要介绍了电子战和雷达系统工程方面的知识和技术。这本手册包括了广泛的主题,涵盖了从设计和开发到部署和维护的全过程,以及包括信息战、辐射信号处理、信号处理技术、电子战系统和雷达系统的详细介绍等方面。 本手册为希望进一步了解和深入研究电子战和雷达系统的工程师、技师和学生提供了一个重要的资源。读者可以通过这本手册获得关于电子战和雷达系统工程基础知识的全面概述,还可以了解最新的技术进展和相关的应用场景。 本手册内容还包括了实际问题的解决方法,涉及了复杂的电子战和雷达系统的设计、分析和测试等方面。并且,本手册也提供了准确和清晰的表达和图表,以便读者能够更加轻松地理解所学的内容。 总的来说,“Electronic Warfare and Radar Systems Engineering Handbook. 4th edition” 是一本对于电子战和雷达系统工程方面很有价值的资源,将会对于工程师、技师和学生在相关领域内的学习与工作有很大的帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值