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;
}

训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)的更多相关文章

  1. 训练指南 UVALive - 3126(DAG最小路径覆盖)

    layout: post title: 训练指南 UVALive - 3126(DAG最小路径覆盖) author: "luowentaoaa" catalog: true mat ...

  2. 训练指南 UVALive - 3415(最大点独立集)

    layout: post title: 训练指南 UVALive - 3415(最大点独立集) author: "luowentaoaa" catalog: true mathja ...

  3. 训练指南 UVALive - 3989(稳定婚姻问题)

    ayout: post title: 训练指南 UVALive - 3989(稳定婚姻问题) author: "luowentaoaa" catalog: true mathjax ...

  4. 训练指南 UVALive - 4043(二分图匹配 + KM算法)

    layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...

  5. 训练指南 UVALive - 5713(最小生成树 + 次小生成树)

    layout: post title: 训练指南 UVALive - 5713(最小生成树 + 次小生成树) author: "luowentaoaa" catalog: true ...

  6. 训练指南 UVALive - 3713 (2-SAT)

    layout: post title: 训练指南 UVALive - 3713 (2-SAT) author: "luowentaoaa" catalog: true mathja ...

  7. 训练指南 UVALive - 4287 (强连通分量+缩点)

    layout: post title: 训练指南 UVALive - 4287 (强连通分量+缩点) author: "luowentaoaa" catalog: true mat ...

  8. 训练指南 UVALive - 5135 (双连通分量)

    layout: post title: 训练指南 UVALive - 5135 (双连通分量) author: "luowentaoaa" catalog: true mathja ...

  9. 训练指南 UVALive - 3523 (双联通分量 + 二分图染色)

    layout: post title: 训练指南 UVALive - 3523 (双联通分量 + 二分图染色) author: "luowentaoaa" catalog: tru ...

随机推荐

  1. MySQL使用笔记(六)条件数据记录查询

    By francis_hao    Dec 17,2016 条件数据记录查询 mysql> select field1,field2-- from table_name where 条件; 其中 ...

  2. Small things are better

    Yesterday I had fun time repairing 1.5Tb ext3 partition, containing many millions of files. Of cours ...

  3. 洛谷P2568 GCD (欧拉函数/莫比乌斯反演)

    P2568 GCD 题目描述 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. 输入输出格式 输入格式: 一个整数N 输出格式: 答案 输入输出样例 输入 ...

  4. [USACO] 2004 Open MooFest 奶牛集会

    题目背景 MooFest, 2004 Open 题目描述 约翰的N 头奶牛每年都会参加"哞哞大会".哞哞大会是奶牛界的盛事.集会上的活动很 多,比如堆干草,跨栅栏,摸牛仔的屁股等等 ...

  5. SCOI2005 互不侵犯 [状压dp]

    题目传送门 题目大意:有n*n个格子,你需要放置k个国王使得它们无法互相攻击,每个国王的攻击范围为上下左走,左上右上左下右下,共8个格子,求最多的方法数 看到题目,是不是一下子就想到了玉米田那道题,如 ...

  6. bzoj 2427 [HAOI2010]软件安装 Tarjan缩点+树形dp

    [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2029  Solved: 811[Submit][Status][Dis ...

  7. Docker Community Edition for CentOS

    Docker CE for CentOS Docker CE for CentOS distribution is the best way to install the Docker platfor ...

  8. vue双向绑定原理

    要了解vue的双向绑定原理,首先得了解Object.defineProperty()方法,因为访问器属性是对象中的一种特殊属性,它不能直接在对象中设置,而必须通过 Object.definePrope ...

  9. uva 11427

    题目大意:每天晚上你都玩纸牌,如果第一次赢了就高高兴兴地去睡觉:如果输了就接着玩,假设每盘游戏获胜的的概率都是p,且各盘游戏相互独立.你是一个固执的完美主义者,因此会一直玩到当晚获胜局数的比例严格大于 ...

  10. 动态规划:划分DP

    划分型动态规划之数的划分 先贴上2014年10月31日的那份代码,甚至怀念当时在机房YY这道题的场面 高中最快乐的时候.. #include<iostream> using namespa ...