首页 > 代码库 > 【csuoj1014】 西湖三人行

【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;}

  

【csuoj1014】 西湖三人行