首页 > 其他分享 >题解:P6880 [JOI 2020 Final] オリンピックバス

题解:P6880 [JOI 2020 Final] オリンピックバス

时间:2024-05-26 11:56:26浏览次数:24  
标签:cnt int 题解 短路 long add 2020 frnt Final

一个比较重要的性质:反转的边要在最短路上才会有贡献。

我们可以先跑一遍最短路,记录下整颗最短路树,然后暴力的对每一条边进行判断,反转。

我们建正反图各两个,分别以 \(1\),\(n\) 为起点。\(n\),\(1\) 为终点。然后对每个图跑最短路,记录下最短路树。

若不反转任何一条边,则答案为 \(1\) 到 \(n\) 再到 \(1\) 的最短路。

然后暴力枚举边,第 \(i\) 条边,考虑将其反转。反转之后 \(1\) 到 \(n\) 的最短路即为 \(1\) 到 \(V_i\) 再从 \(U_i\) 走到 \(n\) 的最短路。往返分开来算。

有一个需要注意的点是,不可以开全局 long long 进行运算,否则只有 5 分

讲的比较少,都在代码里。

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+7;
const int M=207; 
int n,m;
int u[N],v[N];
long long c[N],d[N],ans;
struct node{
	int frnt;
	long long sum1[M],sum2[M];
	bool fl[M],st[N];
	int lst[N];
	struct Map{
		int to,val,nxt,hed;
	}G[N];
	int cnt=0;
	void add(int u,int v,int w){
		G[++cnt].to=v;
		G[cnt].val=w;
		G[cnt].nxt=G[u].hed;
		G[u].hed=cnt;
	}
	void DJ(){
		memset(fl,0,sizeof fl);
		for(int i=1;i<=n+1;i++) sum1[i]=1e9;
		sum1[frnt]=0;
		for(int i=1;i<=n;i++){
			int u=n+1;
			for(int j=1;j<=n;j++) if(!fl[j]&&sum1[j]<sum1[u]) u=j;
			if(u==n+1) break;
			fl[u]=1;
			for(int j=G[u].hed;j;j=G[j].nxt){
				int v=G[j].to,w=G[j].val;
				if(!fl[v]&&sum1[v]>sum1[u]+w){
					sum1[v]=sum1[u]+w;
					lst[v]=j;//给在最短路树上的点打标记。
				}
			}
		}
		for(int i=1;i<=n;i++) if(i!=frnt) st[lst[i]]=1;//这里是计录下最短路树。
	}
	int swp;
	void DJ2(){
		memset(fl,0,sizeof fl);
		for(int i=1;i<=n+1;i++) sum2[i]=1e9;
		sum2[frnt]=0;
		for(int i=1;i<=n;i++){
			int u=n+1;
			for(int j=1;j<=n;j++) if(!fl[j]&&sum2[j]<sum2[u]) u=j;
			if(u==n+1) break;
			fl[u]=1;
			for(int j=G[u].hed;j;j=G[j].nxt){
				int v=G[j].to,w=G[j].val;
				if(!fl[v]&&sum2[v]>sum2[u]+w&&j!=swp){//这里多了一个判断:即不能为翻转之前的边。
					sum2[v]=sum2[u]+w;
				}
			}
		}
	}
	long long work(int u,int end){
		if(!st[u]) return sum1[end];//不在最短路树上 
		swp=u;
		DJ2();
		return sum2[end];
	}
}g[5];
signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n>>m;
	g[1].frnt=g[4].frnt=1,g[2].frnt=g[3].frnt=n;
	for(int i=1;i<=m;i++){
		cin>>u[i]>>v[i]>>c[i]>>d[i];
		g[1].add(u[i],v[i],c[i]);//四个图 
		g[2].add(v[i],u[i],c[i]);
		g[3].add(u[i],v[i],c[i]);
		g[4].add(v[i],u[i],c[i]);
	}
	for(int i=1;i<=4;i++) g[i].DJ();//不反转,求最短路 
	ans=g[1].sum1[n]+g[3].sum1[1];//初始答案 
	for(int i=1;i<=m;i++){//将边反转 
		int go=min(g[1].work(i,n),g[1].work(i,v[i])+c[i]+g[2].work(i,u[i]));//去 
		int back=min(g[3].work(i,1),g[3].work(i,v[i])+c[i]+g[4].work(i,u[i]));//来 
		ans=min(ans,go+back+d[i]);
	}
	if(ans>=1e9) ans=-1;
	cout<<ans;
	return 0;
}

标签:cnt,int,题解,短路,long,add,2020,frnt,Final
From: https://www.cnblogs.com/shootdown/p/18213487

相关文章

  • 题解:CF1119D Frets On Fire
    大水题。首先,若区间内只有一根弦,不会对答案有贡献。我们思考如何对答案产生贡献。我们知道,对于每一个\(s_i\),都会产生一段\(s_i+r-l\)的连续序列,在对\(s\)数组排序后,若每个\(s_i+r-l\ges_{i+1}\)则答案为\(s_n+r-(s_1+l)+1\)。若够不到下一位呢?我们在\(s_n+r-(s_1+l......
  • UVA11922 Permutation Transformer 题解
    题目传送门前置知识无旋treap解法与luoguP3391【模板】文艺平衡树不同的是本题翻转后需要放到整个序列的末尾。由于需要翻转后放到末尾,故无旋Treap在维护文艺平衡树的过程中合并时跳着合并即可。代码#include<bits/stdc++.h>usingnamespacestd;#definelllong......
  • 题解【CF798D Mike and distribution】
    题目链接思考方向:构造方法满足\(A\)的要求,再满足\(B\)的要求。如果只考虑\(A\),有一种显然的方案:将\(A\)从大到小排序,选出前\(\left\lfloor\frac{n}{2}\right\rfloor+1\)大的即可。但这样显然难以扩展,所以需要另寻方案。由于题目提供了额外的\(+1\),所以先将最大的......
  • UVA1674 闪电的能量 Lightning Energy Report 题解
    题目传送门前置知识树链剖分|线段树解法树链剖分后维护一个支持区间修改,单点查询的线段树即可。也可以树上差分,同146.DFS序3,树上差分1的\(1,2\)操作,时间复杂度比树链剖分更优。代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#define......
  • CF1141E Superhero Battle 题解
    题目传送门简化题意给定\(H,n\)和一个长度为\(n\)的序列\(d\),求一个最小的\(m\)使得\(H+\sum\limits_{i=1}^{m}d_{(i-1)\bmodn+1}\le0\)。解法将式子移项后得到\(\sum\limits_{i=1}^{m}-d_{(i-1)\bmodn+1}\geH\)。将\(\sum\limits_{i=1}^{m}-d_{(i-1)\bmo......
  • SP14943 DRTREE - Dynamically-Rooted Tree 题解
    题目传送门前置知识树链剖分|线段树解法树剖换根,子树查询板子。类似换根DP的思路,我们发现换根后仅有祖先、子树、深度等会随祖先的变化而变化。设\(rt_{i}\)表示第\(i\)次操作的树根,\(x_{i}\)表示第\(i\)次操作的节点。接着进行大力分讨。当\(rt_{i}=x_{i}\)......
  • 图的dfs遍历题解
    本蒟蒻又来做题啦!看看今天做啥题。。。。题目描述时间:1s 空间:256M题目描述:给出一个无向图和一个起点s,输出这个图从s结点开始的DFS遍历序列。规定:节点邻居按照输入的顺序遍历输入格式:共M+1行。第11行包含33个正整数N,M,s,表示有N个点,M条边,起点为s。第2~M+1行包含2个用......
  • 【题解】 [USACO 2009 Mar] Cow Frisbee Team S
    题目描述题意分析从\(N\)个整数中取若干个(不能不选),且取的数之和为\(F\)的倍数的总方案数对\(10^8\)取余的值。思路这道题是一道二维线性DP。那么根据线性DP的解题方法。首先,找出题目的阶段性。这道题显而易见方案数随着选择的个数而变化,那么这道题就以选择的个数作为阶段......
  • 【赛题解析】【网络建设与运维】2023年全国职业院校技能大赛中职组“网络建设与运维”
    在此之前,欢迎关注波比网络波比网络官方公众号:blbinet波比网络工作室官方公众号:blbistudio技能大赛各赛项交流群:https://www.blbi.cn/threads/40/更多正式赛题源文件访问:https://www.blbi.cn获取技术支持访问:https://www.blbi.cn/form/1/selectNISP、CIPS、PTE证书可......
  • 【赛题解析】【网络建设与运维】2023年全国职业院校技能大赛中职组“网络建设与运维”
    在此之前,欢迎关注波比网络波比网络官方公众号:blbinet波比网络工作室官方公众号:blbistudio技能大赛各赛项交流群:https://www.blbi.cn/threads/40/更多正式赛题源文件访问:https://www.blbi.cn获取技术支持访问:https://www.blbi.cn/form/1/selectNISP、CIPS、PTE证书可......