首页 > 其他分享 >题解:【ABC291F】Teleporter and Closed off

题解:【ABC291F】Teleporter and Closed off

时间:2023-02-27 10:12:34浏览次数:46  
标签:Teleporter const int 题解 static MAX off dir dis

题目链接

给定一个 \(n\) 个点的图,每个点只向编号最多大于它 \(m\) 的点连单向边,求不经过 \(2 \sim n\) 中的一个点,\(1 \to n\) 的最短路。注意到 \(m\) 很小,这里给出两种做法,都是基于 \(m\) 的特性来做的。

第一种是直接搜索。首先我们求出 \(1\) 到每个点的最短路和 \(n\) 到每个点的最短路。如果说不经过点 \(i\),对于点 \(j\) 有 \(j+k>i (1 /le k /le m,j+k \le n)\) 且有边 \(j \to j+k\) 那就说明存在这条合法路径,直接枚举 \(j\) 和 \(k\) 即可,统计的答案即为 \(dis_{1 \to j} + dis_{j+k \to n} +1\)。

#include<bits/stdc++.h>
#define int long long
using namespace std;

namespace LgxTpre
{
	static const int MAX=100010;
	static const int INF=4557430888798830399;
	static const int mod=998244353;
	
	int n,m,ans;
	string s[MAX];
	
	struct edge
	{
		int nex,to;
	}e[MAX<<5];
	int head[MAX],cnt;
	inline void add(int x,int y)
	{
		e[++cnt].nex=head[x],head[x]=cnt,e[cnt].to=y;
		return;
	}
	
	queue<int> q;
	int dis[MAX][2];
	inline void bfs(int dir)
	{
		if(!dir) q.push(1),dis[1][0]=0;
		else q.push(n),dis[n][1]=0;
		while(!q.empty())
		{
			int now=q.front(); q.pop();
			for(int i=head[now];i;i=e[i].nex)
			{
				int to=e[i].to;
				if(dis[to][dir]>dis[now][dir]+1)
					dis[to][dir]=dis[now][dir]+1,q.push(to);
			}
		}
		return;
	}
	inline void init()
	{
		memset(head,0,sizeof head);
		cnt=0;
	}
	
	inline void lmy_forever()
	{
		cin>>n>>m;
		memset(dis,0x3f,sizeof dis);
		for(int i=1;i<=n;++i) cin>>s[i];
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				if(s[i][j-1]=='1') 
					add(i,i+j);
		bfs(0);
		init();
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				if(s[i][j-1]=='1') 
					add(i+j,i);
		bfs(1);
		for(int i=2;i<n;++i)
		{
			ans=INF;
			for(int j=max(1ll,i-m+1);j<i;++j)
				for(int k=1;k<=m;++k)
					if(j+k>i&&s[j][k-1]=='1')
						ans=min(ans,dis[j][0]+dis[j+k][1]+1);
			if(ans==INF) cout<<-1<<" ";
			else cout<<ans<<" ";
		}
		return;
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	LgxTpre::lmy_forever();
	return (0-0);
}

第二种是矩阵。记 \(d_i\) 为 \(1 \to i\) 的最小花费,设计状态矩阵:

\[\begin{bmatrix} d_i \; d_{i-1} \; d_{i-2} \cdots d_{i-m} \end{bmatrix} \]

由于自带大常数的问题,我的矩阵相比于搜索处于极大的劣势。

#include<bits/stdc++.h>
#define int long long
using namespace std;

namespace LgxTpre
{
	static const int MAX=100010;
	static const int INF=4557430888798830399;
	static const int mod=998244353;
	
	int n,m,ans;
	string s[MAX];
	
	struct Matrix
	{
		static const int qck=15;
		int a[qck][qck];
		Matrix operator * (const Matrix& T) const 
		{
			Matrix res; memset(res.a,0x3f,sizeof res.a);
			for(int i=1;i<=m;++i)
				for(int j=1;j<=m;++j)
					for(int k=1;k<=m;++k)
						res.a[i][j]=min(res.a[i][j],a[i][k]+T.a[k][j]);
			return res;
		}
	}pre[MAX],suf[MAX],bas[MAX];;
	
	inline void lmy_forever()
	{
		cin>>n>>m;
		for(int i=1;i<=n;++i)
			cin>>s[i];
		for(int i=0;i<=n;++i)
			for(int j=1;j<=m;++j)
				for(int k=1;k<=m;++k)
					bas[i].a[j][k]=(k==j+1)?0:INF;	
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				if(s[i][j-1]=='1')
					bas[i+j].a[j][1]=1;
		pre[2]=bas[2];
		for(int i=3;i<=n;++i) pre[i]=pre[i-1]*bas[i];
		suf[n]=bas[n];
		for(int i=n-1;i>=1;--i) suf[i]=bas[i]*suf[i+1];
		for(int i=2;i<n;++i)
		{
			if(i==2) ans=(bas[0]*suf[i+1]).a[1][1];
			else ans=(pre[i-1]*bas[0]*suf[i+1]).a[1][1];
			if(ans==INF) cout<<-1<<" ";
			else cout<<ans<<" ";
		}
		return;
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	LgxTpre::lmy_forever();
	return (0-0);
}

标签:Teleporter,const,int,题解,static,MAX,off,dir,dis
From: https://www.cnblogs.com/LittleTwoawa/p/17158710.html

相关文章

  • 【Eclipse 问题】Eclipse老项目打包war后的WEB-INF目录下没有classes文件夹的问题解决
    1.右键项目Properties2.选中JavaBuildPath中的Source3.点击浏览4.在WEB-INF目录下新建一个classes文件夹,用来存放编译好的class文件。5.完成......
  • 每日一练(剑指offer)二叉树的下一个结点
    输入描述:输入分为2段,第一段是整体的二叉树,第二段是给定二叉树节点的值,后台会将这2个参数组装为一个二叉树局部的子树传入到函数GetNext里面,用户得到的输入只有一个子树根节......
  • 【题解】CTT 2020 Day 1
    目录A.术树数B.树数术C.述树术A.术树数注意到路径+环的组合仍然可行,因为我们可以在无影响的情况下加入环(显然一条边也算二元环)。而对于每条边,如果其在某些环内,只要......
  • 【题解】CTT 2020 Day 3
    目录A.计数鸡B.PerotationC.树特卡克林A.计数鸡考虑\(\sum\limits_{i}\sum\limits_{j>i}[p_i\geqp_j]+[(p_i+h_i)\geqq_j]\),前部分是逆序对,而偶数让人想到行列式......
  • 【题解】CTT 2019 Day 2
    目录A.循环序列B.MatrixC.杀蚂蚁简单版A.循环序列即求\(\sum\limits_{i=0}^{c}{k\choosem+in}\),即\(\frac{1}{n}\sum\limits_{j=0}^{n-1}\sum\limits_{i=0}^{k-m}......
  • 【题解】CTT 2019 Day 1
    目录A.递增树列B.异世界的文章分割者C.时间旅行A.递增树列令\(f_{u,i}\)表示\(u\)的子树,已经用掉\(i\)个点,剩下的点排列满足要求的方案数。考虑方案的计算,用......
  • 【题解】CTT 2018 Day 2
    目录A.宝石游戏B.面国建设C.WechatA.宝石游戏无修改时考虑长链剖分(加整体异或标记)。有修改时分块,不考虑关键点层长链剖分,最后算答案的时候处理关键点层的答案即可。......
  • 题解 CF1776F【Train Splitting】
    题意:有一个\(n\)点\(m\)边简单无向连通图,请用若干(至少为\(2\))种颜色对每条边染色,使得:对于每种颜色,仅由该颜色的边组成的生成子图不连通。对于每两种颜色,仅由该颜色......
  • Codeforces Global Round 15 CF1552 A~G 题解
    点我看题对两三年前的cf进行考古的时候偶然做到这场,像这种全是构造题和思维题的比赛还是比较少见的。题目本身很有意思,但是对于现场打比赛想上分的人来说体验就比较差了。......
  • P6659 [POI 2019] Najmniejsza wspólna wielokrotność 题解
    题意给定一个整数\(M\),求是否存在一个区间\([a,b]\)使得\(M\)为\([a,b]\)这个区间中所有数的最小公倍数。解题方法1.区间长度\(=2\)。二分查找\(a\),由于相......