ICode9

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

[20210404]JZM的国赛路

2021-04-04 19:32:47  阅读:240  来源: 互联网

标签:JZM nm 红绿灯 20210404 tt 国赛 mathcal 复杂度 周期


目录

壹、题面 ¶

§ 1.1.题目背景 §

\(\sf JZM\) 又要去国赛了,但是在去往赛场的时候祂遇到了一个十字路口,这个十字路口包含 \(n\) 个红绿灯,这 \(n\) 个红绿灯有着相同长度的固定的周期 \(T\),在一个周期中,每个红绿灯恰好一次由红变绿,恰好一次由绿变红(并且都是在整数时刻发生改变)。一个红绿灯如果当前是红色则会显示还需要多久变绿。

由于 \(\sf JZM\) 是神祗,祂仅仅看了 \(m\) 眼就推断出这 \(n\) 个红绿灯的周期 \(T\),但是,由于 \(\sf Arextre\) 是个废物,他并没有看出来周期,但是他知道神祗的 \(m\) 个数据,他想请你帮他一下忙,判断这些数据是否能够推算出周期 \(T\),如果可以请输出,否则输出 \(-1\).

§ 1.2.输入输出 §

输入数据

第一行两个整数 \(n,m\),接下来 \(m\) 行每行 \(n\) 个整数 \(x_{i,j}\) 表示观测结果,\(0\) 表示这

个灯是绿灯,否则表示这个红灯还需要多久会变绿。

保证输入数据合法,即只有可能缺失条件,但不存在两个条件之间存在冲突。

输出数据

一行一个整数表示答案。

样例输入1

4 5
0 33 0 36
0 4 0 7
42 2 42 5
0 21 0 24
8 0 8 54

样例输出1

83

样例输入2

2 2
0 100
100 0

样例输出2

-1

§ 1.3.数据范围 §

对于全部数据,\(1\le nm\le 100000,0\le x_{i,j}\le 10000.\)

不要好奇为什么 \(\sf JZM\) 在一个时刻可以同时看 \(100000\) 个红绿灯并且记录下来,因为

\[\color{red}{\huge\text{祂是神}} \]

贰、题解 ¶

绿灯没啥用.

对于同一列来说(即考虑同一个灯),如果有某两个时刻这盏灯都是红灯,那么显然我们可以得到这两行,即这两条信息的时间差,将所有的时间差找出来,如果形成一个收尾相连的环,那么我们就找到其中一个周期,由于题目保证信息相互不冲突,所以,找到最小的周期即为答案。将时间差看成连边,那么我们找的就是环,找环可以使用 \(\tt floyd\) 算法。

考虑这样做的复杂度,建边需要 \(\mathcal O(mn^2)\),跑 \(\tt floyd\) 的复杂度是 \(\mathcal O(m^3)\),如果要卡,可以将 \(m\) 开大一点,然后就 \(gg\) 了......

但是可以使用同样的思路,上面找的是 \(m\) 条信息之间的时间循环,我们可以找 \(n\) 个灯的时间循环,具体地,对于同一条信息,我们可以找到两个红灯,显然可以算出他们的红绿灯切换时间差,同样建边,找到连回到第一个灯的环,从中取最小值,我们也可以得到 \(T\),这样的复杂度就是 \(\mathcal O(nm^2+n^3)\) 咯。

对于 \(n,m\) 择优选择,可以将复杂度控制在 \(\mathcal O(nm\sqrt{nm})\).

一点小优化:

如果我们建图时将权值排序后只连接相邻权值之间的边,那么可以证明两种方法建出来的图中,任意一个简单环的长度都是周期,那么可以 \(\tt dfs\) 求出。这样复杂度就降低到 \(\mathcal O(nm\log n)\).

叁、参考代码 ¶

人太懒了,这是带根的。

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

template<class T>inline T readin(T x){
	x=0; int f=0; char c;
	while((c=getchar())<'0' || '9'<c) if(c=='-') f=1;
	for(x=(c^48); '0'<=(c=getchar()) && c<='9'; x=(x<<1)+(x<<3)+(c^48));
	return f? -x: x;
}

const int maxn=100000;
const int inf=0x3f3f3f3f;

int x[maxn+5], n, m;

inline void input(){
	n=readin(1), m=readin(1);
	if(n<=m){
		for(int i=1; i<=n*m; ++i)
			x[i]=readin(1);
	}
	else{
		for(int i=1; i<=m; ++i)
			for(int j=1; j<=n; ++j)
				x[(j-1)*m+i]=readin(1);
		swap(n, m);
	}
}

int f[325][325];

inline void getf(){
	memset(f, 0x3f, sizeof f);
	for(int i=1; i<=m; ++i)
		for(int j=1; j<=n; ++j) if(x[(i-1)*n+j])
			for(int k=1; k<=n; ++k)
				if(x[(i-1)*n+k]>x[(i-1)*n+j])
					f[j][k]=min(f[j][k], x[(i-1)*n+k]-x[(i-1)*n+j]);
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=n; ++j)
			for(int k=1; k<=n; ++k)
				f[j][k]=min(f[j][k], f[j][i]+f[i][k]);
	int ans=0x3f3f3f3f;
	for(int i=1; i<=n; ++i)
		ans=min(ans, f[i][i]);
	if(ans>=1000000000) puts("-1");
	else printf("%d\n", ans);
}

signed main(){
	freopen("crossing.in", "r", stdin);
	freopen("crossing.out", "w", stdout);
	input();
	getf();
	return 0;
}

肆、用到 の \(\tt trick\) ¶

时间周期?和环可能有莫大关联呢.

标签:JZM,nm,红绿灯,20210404,tt,国赛,mathcal,复杂度,周期
来源: https://www.cnblogs.com/Arextre/p/14616784.html

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

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

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

ICode9版权所有