[SDOI2009]Elaxia的路线 最短路+拓扑排序
时间:2022-06-19
本文章向大家介绍[SDOI2009]Elaxia的路线 最短路+拓扑排序,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题意明确求两个人的最短路最长公共路径
1.所求是一段链,若答案不是连续路径,则两人会有再次相遇的情况,若有再次相遇则对另一方就不是最短路;
2.我们要求最长公共路径,就对每一个点跑最短路,也就是跑4遍,再把两个人重合的地方构建一个新图
如何判断重合,对于x1的最短路 有 dis[1][1~n],同理有dis[2][1~n],dis[3][1~n],dis[4][1~n].
对于一条边 u 到 v 长 w ,重合的条件是 dis[1][u] + dis[2][v] + w = dis[1][y1];这是第一个人的边满足是最短路的条件
第二个人同理 dis[3][u] + dis[4][v] + w = dis[3][y2]。 同时满足这两个条件就是重合的最短路
3.注意方向,由于第二次构图考虑方向,要把两个人同时同向和同时反向分开算。
#include <bits/stdc++.h>
using namespace std;
#define INF 0x7fffffff
const int N = 1550;
int dis[5][N];
int head1[N],head2[N];
int len[N];
int cnt1,cnt2;
int n,m;
struct Edge{
int w,v,nxt;
};
Edge edge1[N*N],edge2[N*N];
int in[N],book[N];
void add1(int u,int v,int w){
cnt1++;
edge1[cnt1].v = v;
edge1[cnt1].w = w;
edge1[cnt1].nxt = head1[u];
head1[u] = cnt1;
}
void add2(int u,int v,int w){
cnt2++;
edge2[cnt2].v = v;
edge2[cnt2].w = w;
edge2[cnt2].nxt = head2[u];
head2[u] = cnt2;
in[v]++;
}
void spfa(int id,int s){
memset(book,0,sizeof(book));
queue<int> q;while(!q.empty())q.pop();
for(int i=1;i<=n;i++)
dis[id][i] = INF;
dis[id][s]=0; book[s]=1; q.push(s);
while(!q.empty()){
int u=q.front(); book[u]=0; q.pop();
for(int w,v,i=head1[u];i;i=edge1[i].nxt){
v = edge1[i].v; w = edge1[i].w+dis[id][u];
if(dis[id][v]>w){
dis[id][v]=w;
if(!book[v]) book[v]=1,q.push(v);
}
}
}
}
void topo(){
queue<int> q;while(!q.empty())q.pop();
for(int i=1;i<=n;i++)if(!in[i])q.push(i);
while(!q.empty()){
int u = q.front(); q.pop();
for(int v,w,i=head2[u];i;i=edge2[i].nxt){
v = edge2[i].v; w = edge2[i].w + len[u];
len[v] = max(len[v],w);
in[v]--;
if(!in[v])q.push(v);
}
}
}
int main()
{
scanf("%d %d",&n,&m);
int x1,y1,x2,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
add1(u,v,w);
add1(v,u,w);
}
spfa(1,x1); spfa(2,y1);
spfa(3,x2);
spfa(4,y2);
// printf("%d",dis[3][4]);
// printf("%dn",dis[3][8]);
for(int i=1;i<=n;i++)
{
for(int j=head1[i];j;j=edge1[j].nxt)
{ int v = edge1[j].v,w = edge1[j].w;
if(dis[1][i]+dis[2][v]+w==dis[1][y1]){
if(dis[3][i]+dis[4][v]+w==dis[3][y2])
add2(i,v,w);
}
}
}
topo();
int ans = 0;
for(int i=1;i<=n;i++)ans=max(ans,len[i]);
//printf("%dn",ans);
memset(len,0,sizeof(len));
memset(in,0,sizeof(in));
for(int i=1;i<=n;i++)
{
for(int j=head1[i];j;j=edge1[j].nxt)
{ int v = edge1[j].v,w = edge1[j].w;
if(dis[1][i]+dis[2][v]+w==dis[1][y1]){
if(dis[3][v]+dis[4][i]+w==dis[3][y2])
add2(i,v,w);
}
}
}
topo();
for(int i=1;i<=n;i++)ans=max(ans,len[i]);
printf("%dn",ans);
return 0;
}
- 那些年我们用Java写过的小游戏 --- 快速击键系统
- 那些年我们的(具有含金量)MySQL测试题目
- Java 异常处理之 论 finally块何时候不走
- Java 中的异常处理机制
- Java 关于接口的那点事儿
- 论 Java 中的内存分配
- Javascript基础回顾 之(一) 类型
- Javascript基础回顾 之(三) 面向对象
- Javascript基础回顾 之(二) 作用域
- 一不小心写了个WEB服务器
- 遍历算法(1)
- Membership三步曲之入门篇 - Membership基础示例
- Java-String.intern的深入研究
- 从Membership 到 .NET4.5 之 ASP.NET Identity
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法