ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

nflsoj 20034 #10302.「2020联考北附1」山遥路远

2021-10-02 15:04:03  阅读:178  来源: 互联网

标签:北附 leq int make vis 405 pair 联考 山遥路远


给你一个 \(n\) 个点,\(m\) 条边的有向图,每条有向边有一个长度 \(w\),且上面有一个字符,这个字符只可能是左括号或者右括号,即 \((\) 或 \()\) 。

我们称一条路径是合法路径,满足其经过的所有字符拼接起来得到的括号串是一个合法括号序列。

接下来有 \(q\) 组询问,每次询问给出节点 \(s,t\) ,问 \(s\) 到 \(t\) 是否存在一条合法路径,如果存在,那么请输出其最短合法路径的长度。由于答案可能很大,你只需要输出答案模 \(998244353\) 的结果。注意这个图可能有重边和自环。

\(1\leq n\leq 400,1\leq m\leq 5\times 10^4,1\leq q\leq 10^5,0\leq w\leq 10^8\)

时限 : 1500ms

空间 : 512mb

看到模 \(998244353\) ,我就害怕了 .

以为本题跟矩阵之类的东西有关,其实不然 .

看到这个最小代价,还可以向最短路上想 .

用 \(f(i,j)\) 表示从节点 \(i\) 到节点 \(j\) 合法串的最小代价.

那么,对于 \(f(i,j)\) 可以扩展到什么 .

  1. 把当前合法串和另一个合法串拼在一起

    \([i\to j]+[j\to k]=[i\to k]\) \(f(i,k)=\min(f(i,k),f(i,j)+f(j,k))\)

    \([k\to i]+[i\to j]=[k\to j]\) \(f(k,j)=\min(f(k,j),f(k,i)+f(i,j))\)

  2. 在当前串左右两边加上一个括号 \((+[i\to j]+)\)

    \(f(k,l)=f(i,j)+w(i,k)+w(j,l)\)

对于状态 \((i,j)\) 就可以转移到别的状态了 . 最短路的图也就明了了 .

初始状态即是 \(f(i,i)=0\) .

第一种扩展是 \(\mathrm O(n^3)\) 的,第二种是 \(\mathrm O(nm^2)\) 的.

再加上 dijkstra 的 \(\log\),总的时间复杂度是 \(\mathrm O((n^3+m^2)\log n^2)\) 的.

瓶颈在第二种转移上,先添加一个左括号,再添加一个右括号,这样分步扩展 .

此时,需新建一个状态 \(g(i,j)\) 表示从节点 \(i\) 到节点 \(j\) 合法串再带一个左括号的最小代价 .

这样,第一个转移不变,第二个转移变成,\(f(k,j)=f(i,j)+w(k,j)\)

对于 \(g(i,j)\) 的转移是, \(f(i,k)=g(i,j)+w(k,j)\) .

这样,拆成了两个 \(\mathrm O(m)\) 的 .

实现的时候把 \(f\) 和 \(g\) 放在一个 priority_queue 里,时间复杂度是 \(\mathrm O((n^3+nm)\log n^2)\) 的.

理论上可以,但是我人傻常数大,所以就 t 了 .

可以考虑,这种转移是边比较多,用 priority_queue 可能别多次加入,不划算,用 spfa 更好一些 ,或者是自己手写堆 .

时间复杂度 : \(\mathrm O(k(n^3+nm))\)

空间复杂度 : \(\mathrm O(n^2+m)\)

code

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	int res=0;
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return res;
}
inline void print(int res){
	if(res==0){
		putchar('0');
		return;
	}
	int a[10],len=0;
	while(res>0){
		a[len++]=res%10;
		res/=10;
	}
	for(int i=len-1;i>=0;i--)
		putchar(a[i]+'0');
}
const long long inf=1e18+10;
const int mod=998244353;
int n,m,q;
vector<pair<int,int> >nei[405][2],rnei[405][2];
long long f[405][405],g[405][405];
bool vis[405][405][2];
queue<pair<bool,pair<int,int> > >que;
int main(){
	freopen("distant.in","r",stdin);
	freopen("distant.out","w",stdout);
	n=read();m=read();q=read();
	for(int i=0;i<m;i++){
		int u=read()-1,v=read()-1,w=read(),t=read()-1;
		nei[u][t].push_back(make_pair(v,w));
		rnei[v][t].push_back(make_pair(u,w));
	}
	for(int i=0;i<n;i++)for(int j=0;j<n;j++){
		f[i][j]=g[i][j]=inf;
	}
	for(int i=0;i<n;i++){
		f[i][i]=0;
		vis[i][i][0]=true;
		que.push(make_pair(0,make_pair(i,i)));
	}
	while(!que.empty()){
		int t=que.front().first;
		int u=que.front().second.first,v=que.front().second.second;
		que.pop();
		vis[u][v][t]=false;
		if(t==0){
			for(int i=0;i<n;i++){
				if(f[u][i]>f[u][v]+f[v][i]){
					f[u][i]=f[u][v]+f[v][i];
					if(!vis[u][i][0]){
						vis[u][i][0]=true;
						que.push(make_pair(0,make_pair(u,i)));
					}
				}
				if(f[i][v]>f[i][u]+f[u][v]){
					f[i][v]=f[i][u]+f[u][v];
					if(!vis[i][v][0]){
						vis[i][v][0]=true;
						que.push(make_pair(0,make_pair(i,v)));
					}
				}
			}
			for(int i=0;i<(int)rnei[u][0].size();i++){
				int to=rnei[u][0][i].first,w=rnei[u][0][i].second;
				if(g[to][v]>f[u][v]+w){
					g[to][v]=f[u][v]+w;
					if(!vis[to][v][1]){
						vis[to][v][1]=true;
						que.push(make_pair(1,make_pair(to,v)));
					}
				}
			}
		}
		else{
			for(int i=0;i<(int)nei[v][1].size();i++){
				int to=nei[v][1][i].first,w=nei[v][1][i].second;
				if(f[u][to]>g[u][v]+w){
					f[u][to]=g[u][v]+w;
					if(!vis[u][to][0]){
						vis[u][to][0]=true;
						que.push(make_pair(0,make_pair(u,to)));
					}
				}
			}
		}
	}
	for(int i=0;i<n;i++)for(int j=0;j<n;j++){
		if(f[i][j]==inf)f[i][j]=-1;
		else f[i][j]%=mod;
	}
	for(int i=0;i<q;i++){
		int s=read()-1,t=read()-1;
		if(f[s][t]==-1){
			putchar('-');
			putchar('1');
		}
		else{
			print(f[s][t]);
		}
		putchar('\n');
	}
	return 0;
}
/*inline? ll or int? size? min max?*/

标签:北附,leq,int,make,vis,405,pair,联考,山遥路远
来源: https://www.cnblogs.com/suadwm/p/15361912.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有