[SCOI2006]城堡

link & 博客园食用

这种做法需要吸氧才能通过,不是正解,所以只是提供一种题解区还没有的思路。

可以用分层图的思路来做这道题。每次从一个方格转移到另一个方格时时间都发生了改变,时间的改变可以看成是不同层次的图之间的转移,所以只需要按照题意在相邻的两层图之间连边跑最短路即可。显然假如所有方块的周期的最小公倍数是 \(lcm\) ,那么所有位置相同、时间模这个公倍数相同的状态在转移上是完全一样的,可以看成是同一个状态,所以第 \(lcm-1\) 层图应该向第 \(0\) 层图连边。其它有些细节比如建立超级源点(它可以一直呆在最开始节点上不出去)和超级汇点方便敲代码就是分层图的基本操作了。

#include<bits/stdc++.h>
//#define feyn
#define p(a,b) (a*(m+2)+b+2)
const int N=3000010;
const int M=1010;
const int R=12;
using namespace std;
inline void read(int &wh){
	wh=0;int f=1;char w=getchar();
	while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
	while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
	wh*=f;return;
}

inline int gcd(int s1,int s2){
	return s2==0?s1:gcd(s2,s1%s2);
}
inline int lcm(int s1,int s2){
	return s1*s2/gcd(s1,s2);
}

int m,lc=1,num[M],a[M][R];

struct edge{
	int t,v,next;
}e[N*3];
int head[N],esum;
inline void add(int fr,int to,int val){
	e[++esum]=(edge){to,val,head[fr]};head[fr]=esum;
}

int dis[N];
bool vis[N];
struct node{
	int pl,dis;
};
inline bool operator <(node s1,node s2){
	return s2.dis<s1.dis;
}
priority_queue<node>q;

signed main(){
	
	#ifdef feyn
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);
	for(int i=1;i<=m;i++){
		read(num[i]);lc=lcm(lc,num[i]);
		for(int j=0;j<num[i];j++)read(a[i][j]);
	}
	num[0]=num[m+1]=1;
	//0 to 1
	//S to 0
	//m+1 to T
	for(int i=0;i<lc;i++){
		add(0,p(i,0),0);
		add(p(i,(m+1)),1,0);
		int nt=(i+1)%lc;
		add(p(i,0),p(nt,1),a[1][nt%num[1]]);
	}
	for(int i=1;i<=m;i++){
		for(int t=0;t<lc;t++){
			int nt=(t+1)%lc;
			add(p(t,i),p(nt,i),a[i][nt%num[i]]);
			add(p(t,i),p(nt,i+1),a[i+1][nt%num[i+1]]);
			add(p(t,i),p(nt,i-1),a[i-1][nt%num[i-1]]);
		}
	}
	
	memset(dis,0x3f,sizeof(dis));
	dis[0]=0;q.push((node){0,0});
	while(!q.empty()){
		node now=q.top();q.pop();
		int wh=now.pl,nd=now.dis;
		if(vis[wh])continue;vis[wh]=true;
		for(int i=head[wh],th;i;i=e[i].next){
			int nval=dis[wh]+e[i].v;th=e[i].t;
			if(nval<dis[th]){
				dis[th]=nval;q.push((node){th,dis[th]});
			}
		}
	}
	
	printf("%d",dis[1]);
	
	return 0;
}
posted @ 2022-07-06 14:06  Feyn618  阅读(25)  评论(0编辑  收藏  举报