【csuoj1014】 西湖三人行

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1014 (题目链接)

题意

  从无向图图上一点到达另一点,可以步行,搭公交或者是打的,不同的交通方式花的钱不同,当然消耗的时间也不同。求从起点S到终点T在花费的总钱数少于L的情况下的最短时间。

Solution

  应YZC的邀请做了这道题,就是一个分层图最短路,转移有点恶心。

细节

  注意初始化,以及公交车两两之间走的不是最短路,而是两点之间的直接相连的边。

代码

// codevs1199
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#define LL long long
#define inf 1000000000
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=200,maxm=1010,maxw=3010;
struct edge {int to,next,w;}e[maxm<<1];
struct data {int num,w;};
int head[maxn],vis[maxn][maxw],t[maxn][maxn],n,m,S,T,B,L,cnt;
int dis[maxn][maxw],f[maxn][maxn],d[maxn][maxn];
vector<int> v[maxn];
queue<data> q;

void link(int u,int v,int w) {
	e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
	e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;e[cnt].w=w;
}
void Init() {
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++) f[i][j]=d[i][j]=inf;
	for (int i=1;i<=n;i++) f[i][i]=head[i]=0;
	for (int i=1;i<=n;i++) v[i].clear();
	while (!q.empty()) q.pop();
	cnt=0;
}
void Floyed() {
	for (int k=1;k<=n;k++)
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				if (i!=j && j!=k && i!=k)
					f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
void walk(data x) {
	for (int i=head[x.num];i;i=e[i].next)
		if (dis[e[i].to][x.w+e[i].w*3]>dis[x.num][x.w]+e[i].w*1000) {
			dis[e[i].to][x.w+e[i].w*3]=dis[x.num][x.w]+e[i].w*1000;
			if (!vis[e[i].to][x.w+e[i].w*3]) {
				q.push((data){e[i].to,x.w+e[i].w*3});
				vis[e[i].to][x.w+e[i].w*3]=1;
			}
		}
}
void bus(data x) {
	for (int i=0;i<(int)v[x.num].size();i++) {
		int s,p=v[x.num][i];
		for (s=1;s<=t[p][0];s++) if (t[p][s]==x.num) break;
		s++;
		double D=0;
		for (s;s<=t[p][0];s++) {
			D+=d[t[p][s-1]][t[p][s]];
			if (dis[t[p][s]][x.w+6]>dis[x.num][x.w]+D*250) {
				dis[t[p][s]][x.w+6]=dis[x.num][x.w]+D*250;
				if (!vis[t[p][s]][x.w+6]) {
					q.push((data){t[p][s],x.w+6});
					vis[t[p][s]][x.w+6]=1;
				}
			}
		}
	}
}
void taxi(data x) {
	for (int i=1;i<=n;i++) if (i!=x.num) {
			int W=x.w+10+(f[x.num][i]>3 ? 2*(f[x.num][i]-3) : 0);
			if (dis[i][W]>dis[x.num][x.w]+f[x.num][i]*125) {
				dis[i][W]=dis[x.num][x.w]+f[x.num][i]*125;
				if (!vis[i][W]) {
					q.push((data){i,W});
					vis[i][W]=1;
				}
			}
		}
}
void SPFA(int s) {
	for (int i=1;i<=n;i++)
		for (int j=0;j<=L;j++) dis[i][j]=inf;
	dis[s][0]=0;
	q.push((data){s,0});
	while (!q.empty()) {
		data x=q.front();q.pop();
		vis[x.num][x.w]=0;
		walk(x);
		bus(x);
		taxi(x);
	}
}
int main() {
	int Case;scanf("%d",&Case);
	while (Case--) {
		scanf("%d%d%d%d%d%d",&L,&n,&m,&S,&T,&B);
		Init();
		for (int uu,vv,ww,i=1;i<=m;i++) {
			scanf("%d%d%d",&uu,&vv,&ww);
			link(uu,vv,ww);
			d[uu][vv]=d[vv][uu]=f[uu][vv]=f[vv][uu]=ww;
		}
		for (int i=1;i<=B;i++) {
			scanf("%d",&t[i][0]);
			for (int j=1;j<=t[i][0];j++) {
				scanf("%d",&t[i][j]);
				v[t[i][j]].push_back(i);
			}
		}
		Floyed();
		SPFA(S);
		int ans=inf;
		for (int i=0;i<=L;i++) ans=min(ans,dis[T][i]);
		if (ans==inf) printf("no\n");
		else printf("%d\n",ans);
	}
	return 0;
}

  

时间: 2024-12-15 19:13:55

【csuoj1014】 西湖三人行的相关文章

雪中西湖游

南京出差,期间的周末专程去杭州转了转,当年玩仙剑奇侠传的时候,把游戏中的临安城(杭州南宋古称)转了多遍 ,真身还真的是第一次来杭州城.本来还打算约上阿里的朋友,到阿里研发中心参观参观,最后因为时间有限,也就转了转西湖和雷峰塔. 这几天刚好赶上寒潮,杭州下了大雪,特别冷,我把能穿上的衣服都穿上了.雪下的西湖少了些清秀,多了些婀娜,非常的美.因为下雪,游人也不多,一个人在雪中傻乎乎的把西湖绕了一圈.十多公里走下来,衣服鞋子都湿透了,回到酒店,为了能暖和些,还买了壶绍兴女儿红来暖身,才算好些.

西湖小型张值得收藏吗

西湖,地处浙江省杭州市,是中国大陆首批国家重点风景名胜区和中国十大风景名胜之一,是现今<世界遗产名录>中少数几个和中国唯一一个湖泊类文化遗产.古语"上有天堂,下有苏杭",可见杭州在人们的心中甚至可与天堂媲美,足以见得其景观之美. 西湖以其独特的文化底蕴,美不胜收的雅致景观登上国家名片邮票.1989年11月25日,中国邮政局经严格审核之后发行西湖邮票,共4枚外加1枚小型张.该邮票分别选取苏堤春晓.曲院风荷.三潭印月.断桥残雪四处景观为画面,再现了西湖春夏秋冬4季的不同风光.(

户外生活--西湖林至千军台

户外生活--西湖林至千军台    冬日的暖阳,洒在幽静的白桦林:清新的空气,伴着脚下的冰雪,我们2015踏雪而行:24km,我们在快乐和轻松中奔跑,奔跑吧快乐的户外达人.

VR技术驱动智慧旅游,自由漫步西湖不是梦

虚拟现实技术是今年最热门的科技之一,不少行业都在嫁接VR功能,其中旅游业也具备这方面的优势.VR+旅游,能让你足不出户即可感受清净唯美的名胜古迹.据591ARVR资讯网www.591arvr.com报道,近日,杭州西湖博物馆推出了"全景漫游虚拟西湖"体验项目,足不出户,拿着手机.戴上VR头盔就可以领略西湖全景. 据悉,想要体验该项目有三种方法.     第一种是在手机上体验,在"杭州西湖博物馆非常西湖"的微信公众号上,有西湖全景的板块,点击就可以体验360度西湖全景

西湖徒步

此西湖非彼西湖,在公司搬家的时候就知道附近有个西湖公园适合散步,今天下了班决定去感受下. 说是附近其实也还有相当一段距离,趁着雨后这潮湿的天气活动活动,看看今天能否重登久违的运动榜首,上次的徒步橘子洲遇到心血来潮搞长跑的哥们,只能饮恨屈居第二,试试今天的运气. 20多分钟走到公园入口,一个简易的门,旁边立着一块同样简易的牌子上写着西湖文化园,在配以几个进园注意事项的图示,连个简介都没有,看来是刚开放没多久. 公园里路面修的很好,有点类似塑胶跑道的意思,比较适合散步和慢跑,所以这里聚集了不少运动健

杭州 - 西湖 - 绿茶餐厅

感谢双双的盛情,载我领略西湖全景,还有那一路幽幽的龙井清香. 这里的剁椒鱼头和坩埚包菜很Nice

1088 三人行 (20 分)

子曰:“三人行,必有我师焉.择其善者而从之,其不善者而改之.” 本题给定甲.乙.丙三个人的能力值关系为:甲的能力值确定是 2 位正整数:把甲的能力值的 2 个数字调换位置就是乙的能力值:甲乙两人能力差是丙的能力值的 X 倍:乙的能力值是丙的 Y 倍.请你指出谁比你强应“从之”,谁比你弱应“改之”. 输入格式: 输入在一行中给出三个数,依次为:M(你自己的能力值).X 和 Y.三个数字均为不超过 1000 的正整数. 输出格式: 在一行中首先输出甲的能力值,随后依次输出甲.乙.丙三人与你的关系:如

1088 三人行

子曰:“三人行,必有我师焉.择其善者而从之,其不善者而改之.” 本题给定甲.乙.丙三个人的能力值关系为:甲的能力值确定是 2 位正整数:把甲的能力值的 2 个数字调换位置就是乙的能力值:甲乙两人能力差是丙的能力值的 X 倍:乙的能力值是丙的 Y 倍.请你指出谁比你强应“从之”,谁比你弱应“改之”. 输入格式: 输入在一行中给出三个数,依次为:M(你自己的能力值).X 和 Y.三个数字均为不超过 1000 的正整数. 输出格式: 在一行中首先输出甲的能力值,随后依次输出甲.乙.丙三人与你的关系:如

PAT 1088 三人行

1088 三人行 注:丙可是小数 #include<iostream> #include<string.h> #include<math.h> using namespace std; int main(){ int m, x, y, flag=0; double ans[3]; cin>>m>>x>>y; for(int i=99; i>9; i--){ int t=10*(i%10)+i/10; if(double(abs(