训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)
layout: post
title: 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- Dijkstra
- 最短路树
- 图论
- 训练指南
Warfare And Logistics
题意
①先求任意两点间的最短路径累加和,其中不连通的边权为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;
}
训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)的更多相关文章
- 训练指南 UVALive - 3126(DAG最小路径覆盖)
layout: post title: 训练指南 UVALive - 3126(DAG最小路径覆盖) author: "luowentaoaa" catalog: true mat ...
- 训练指南 UVALive - 3415(最大点独立集)
layout: post title: 训练指南 UVALive - 3415(最大点独立集) author: "luowentaoaa" catalog: true mathja ...
- 训练指南 UVALive - 3989(稳定婚姻问题)
ayout: post title: 训练指南 UVALive - 3989(稳定婚姻问题) author: "luowentaoaa" catalog: true mathjax ...
- 训练指南 UVALive - 4043(二分图匹配 + KM算法)
layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...
- 训练指南 UVALive - 5713(最小生成树 + 次小生成树)
layout: post title: 训练指南 UVALive - 5713(最小生成树 + 次小生成树) author: "luowentaoaa" catalog: true ...
- 训练指南 UVALive - 3713 (2-SAT)
layout: post title: 训练指南 UVALive - 3713 (2-SAT) author: "luowentaoaa" catalog: true mathja ...
- 训练指南 UVALive - 4287 (强连通分量+缩点)
layout: post title: 训练指南 UVALive - 4287 (强连通分量+缩点) author: "luowentaoaa" catalog: true mat ...
- 训练指南 UVALive - 5135 (双连通分量)
layout: post title: 训练指南 UVALive - 5135 (双连通分量) author: "luowentaoaa" catalog: true mathja ...
- 训练指南 UVALive - 3523 (双联通分量 + 二分图染色)
layout: post title: 训练指南 UVALive - 3523 (双联通分量 + 二分图染色) author: "luowentaoaa" catalog: tru ...
随机推荐
- P4018 Roy&October之取石子
题目背景 Roy和October两人在玩一个取石子的游戏. 题目描述 游戏规则是这样的:共有n个石子,两人每次都只能取 p^kpk 个(p为质数,k为自然数,且 p^kpk 小于等于当前剩余石子数), ...
- arc073 F many moves(dp + 线段树)
设dp[i][y]表示一个点在x[i],另一个点在y时最小要走的步数 那么有以下转移 对于y != x[i-1]的状态,可以证明,他们直接加|x[i] - x[i-1]|即可(如果有其他方案,不符合对 ...
- 【题解】NOIP2016愤怒的小鸟
一眼n<=18状压dp……方程什么的都很显然,枚举两只小鸟,再将这条抛物线上的小鸟抓出来就好啦.只是这样O(n^3)的dp必然是要TLE的,我一开始这样交上去显然跑得巨慢无比,后来转念一想:面对 ...
- MySQL使用笔记(一)安装配置
By francis_hao Nov 27,2016 一般软件的安装都是可以通过源码和安装包安装,源码安装可配置性好些,安装包安装比较省事,况且使用yum也可以解决依赖的问题,基本实现了一键 ...
- Codeforces Round #328 (Div. 2) A
A. PawnChess time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- word公式编辑中的转义字符
Some of the commonly used symbols: \infty - Infinity \leq - Less then or equal \geq - ...
- centos网络配置之桥接模式
一:前沿 来这家公司好久了,都没有开始写博客,都是积累着,都没有去写,今天实在是天激动了,我的虚拟机在配置好了之后折腾了一天都没有折腾出来可以上网,今天来了继续折腾,然后我该ip,改连接方式,我擦,终 ...
- js实现2048小游戏
这是学完javascript基础,编写的入门级web小游戏 游戏规则:在玩法规则也非常的简单,一开始方格内会出现2或者4等这两个小数字,玩家只需要上下左右其中一个方向来移动出现的数字,所有的数字就会想 ...
- #error#storyboard#xib#解决方案
https://www.evernote.com/shard/s227/sh/cad7d5f5-8e81-4b3b-908f-5d8eee7d11e2/928786149cf9a103a74626 ...
- Codeforces Round #391 A B C D E
A. Gotta Catch Em' All! 题意 从给定的字符串中选取字符,问可构成多少个\(Bulbasaur\) // 想到柯南里一些从报纸上剪汉字拼成的恐吓信_(:з」∠)_ Code #i ...