首页 > 其他分享 >题解 [SDOI2009] Elaxia的路线

题解 [SDOI2009] Elaxia的路线

时间:2023-08-09 23:55:04浏览次数:54  
标签:opt dij int 题解 st SDOI2009 rightarrow Elaxia dis

题目链接

题意简述:求两条给定起点终点最短路的最长公共路径。

首先最长公共路径一定是两条最短路的公共最长链的部分。至少一定在两条最短路上。

考虑如何求出一条路径是否包含于一条最短路,只要路径 \(x\rightarrow y\) 满足:

\[dis_{st\rightarrow x}+w_{x\rightarrow y}+dis_{y\rightarrow ed}=dis_{st\rightarrow ed} \]

就说明该路径为最短路上的一条边。

但是重合部分并不一定是两条路径的重合部分,有可能是两条路径的多种情况混在一块,先来考虑简单情况,两条最短路相加,重合部分方向(记 \(st\) 走到 \(ed\) 为方向)要么是相同,要么是相反,这是好证的;同理,若两个重合部分方向相同且连在一起,则说明他们一定是在同一条最短路上的。所以我们分别保留方向相同,方向相反的边,依次做一遍 \(dag\) 上的 \(dp\) 即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

#define PII pair<int,int>
const int N=1600;
int n,m;
int s1,e1,s2,e2;
struct node{
	int to,w;
};
vector<node> g[N],g2[N];
int dis[10][N];
int f[N];
priority_queue<PII> q;

void dij(int st,int opt) {
	memset(dis[opt],0x3f,sizeof(dis[opt]));
	memset(f,0,sizeof(f));
	while(q.size()) q.pop();
	q.push({0,st}); dis[opt][st]=0;
	while(q.size()) {
		int x=q.top().second; q.pop();
		if(f[x]) continue;
		f[x]=1;
		for(auto t:g[x]) {
			int y=t.to,w=t.w;
			if(dis[opt][y]>dis[opt][x]+w) {
				dis[opt][y]=dis[opt][x]+w;
				if(!f[y]) q.push({-dis[opt][y],y});
			}
		}
	}
}

int deg[N],len[N];
void topo() {
	queue<int> q;
	while(q.size()) q.pop();
	for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
	while(q.size()) {
		int x=q.front(); q.pop();
		for(node t:g2[x]) {
			int y=t.to,w=t.w;
			deg[y]--;
			len[y]=max(len[y],len[x]+w);
			if(!deg[y]) q.push(y);
		}
	}
}

int main() {
	cin>>n>>m;
	cin>>s1>>e1>>s2>>e2;
	for(int i=1;i<=m;i++) {
		int x,y,z; cin>>x>>y>>z;
		g[x].push_back({y,z});
		g[y].push_back({x,z}); 
	}
	dij(s1,1); dij(e1,2); dij(s2,3); dij(e2,4);
	
	for(int i=1;i<=n;i++) {
		for(auto t:g[i]) {
			int x=i,y=t.to,w=t.w;
			if(dis[1][x]+w+dis[2][y]==dis[1][e1]&&dis[3][x]+w+dis[4][y]==dis[3][e2]) {
				g2[x].push_back({y,w});
				deg[y]++;
			}
		}
	} 
	topo();
	int ans=0;
	for(int i=1;i<=n;i++) ans=max(ans,len[i]);
	for(int i=1;i<=n;i++) {
		g2[i].clear();
		deg[i]=0; len[i]=0;
	}
	for(int i=1;i<=n;i++) {
		for(auto t:g[i]) {
			int x=i,y=t.to,w=t.w;
			if(dis[1][x]+w+dis[2][y]==dis[1][e1]&&dis[3][y]+w+dis[4][x]==dis[3][e2]) {
				g2[x].push_back({y,w});
				deg[y]++;
			}
		}
	}	
	topo();
	for(int i=1;i<=n;i++) ans=max(ans,len[i]);
	
	cout<<ans;
	
	return 0;
}

标签:opt,dij,int,题解,st,SDOI2009,rightarrow,Elaxia,dis
From: https://www.cnblogs.com/zhangyuzhe/p/17619131.html

相关文章

  • keepalived 邮件通知无法发送邮件问题解决【亲测有效,没有效果来找我】
    环境keepalivedkeepalived-2.2.7操作系统cenos7安装方式源码编译安装问题最近在安装keepalived高可用服务,环境是安装完了,但是我想要使用邮件通知这个功能,通过网上捞针怎么也不成功,真是绝绝子,折磨我1天多。终于在刚刚得到了解决办法解决在vrrp_instance自定义的名字中添加......
  • iPhone上使用Charles 抓包的配置方法与问题解决方式
    我是在Macos下配置的,其它平台的内容和步骤也差不多。配置方法:(网上很多,大致说下)一、Charles下载:1)官网下载地址:https://www.charlesproxy.com/download/  二、Charles配置代理:1)查看本机IP:help-->LocalIPAddress   2)查看或者设置访问端口:Proxy->ProxySettings三、配置ios手......
  • P9511 『STA - R3』大豆 题解--zhengjun
    妙妙题。题意给定\(F_0(x)=a_{(x-1)\bmodn+1}\)。\[F_k(x)=F_{k-1}(x)-\sum\limits_{i=2}^nF_k(\lfloor\frac{n}{i}\rfloor)\]求\(F_k(m)\)。\(1\len\le10^4,1\lem\le10^{10},1\lek\le3\)。直接数论分块求解的复杂度是\(O(m^{\frac{3}{4}}k)\),难以通过。如果像......
  • 大连人工智能计算平台——华为昇腾AI平台——高性能计算HPC的pytorch源码编译报错——
     如题:pytorch源码编译报错——USE_CUDA=OFF  在编译pytorch源码的时候发现错误,虽然编译环境中已经安装好CUDA和cudnn,环境变量也都设置好,但是编译好的pytorch包wheel总是在运行torch.cuda.is_available()显示false,于是从编译源码的过程中进行重新检查,发现在编译的过程中提......
  • 8 月 9 日测试题解
    集体被大样例薄纱了。T1P1292有两个容量分别为\(a\)与\(b\)的酒杯与一个容量无限的酒桶,有以下几种操作:用酒桶将\(a\)倒满;将\(b\)中的酒全部倒入酒桶;将\(b\)中的酒倒入\(a\),直到\(a\)被装满或\(b\)被倒空。问\(a\)中可能倒出的最少的酒是多少以及分别至......
  • 题解 CF1857G【Counting Graphs】
    一个非常显然的事情是:总方案数即为每条边方案数之积。树边已经确定,考察每条非树边\((u,v)\)可以怎么取。给定的树\(T\)是唯一最小生成树,这意味着非树边\((u,v)\)要么不存在,要么权值大于\(T\)上\((u,v)\)之间任意一条边的权值。设\(T\)上\((u,v)\)间的最大边权为\(......
  • 杭电多校 2023 杂题题解
    打算只写点有意思的题。D1JEasyproblemI注意到\(x_i\)单增,所以一个数被减到负数之后,所有的操作都会将它减到负数,也就等价于乘\(-1\)再相加。使用一棵线段树维护所有数,将这些数分为两种,一种如上,一种是区间减。最终所有数都会变为需要乘\(-1\)再相加的数,于是只要每次精......
  • luogu P4200 千山鸟飞绝 题解 【一维数组套平衡树】
    目录题目解题思路code题目题目链接解题思路首先,此题有明显的插入、删除、查找,所以必须要使用平衡树。考虑如何使用平衡树维护每个鸟的状态。发现很不方便,因为鸟的位置改变,整个平衡树的值都要修改。考虑针对每个节点开一颗平衡树,这样就有\(3e4\times3e4\)棵树。这显然太多了......
  • P9507 [BalkanOI2018] Popa 题解
    原题传送门题目描述Ghiță有一个下标从\(0\)开始的正整数序列\(S\)。因为他是喀尔巴阡的国王,所以他想要构造一个节点编号为\(0,1,\ldots,N-1\)的二叉树,满足:树的中序遍历按节点编号升序排列。二叉树的中序遍历由以根的左子节点(如果存在)为根形成的子树的中序遍历,根的节......
  • 桐柏邀请赛 S15 题解
    定位:给中低段位一点压力,给中高段位一点信心!A发现只是单向变换\((0\to1)\),用两个变量维护位置最小值和最大值即可。#defineintlonglongintn,q,maxn,minn=1e18+1,x;signedmain(){ n=read(),q=read(); while(q--){ x=read(); maxn=max(maxn,x); minn=min(minn,x......