zoukankan      html  css  js  c++  java
  • 【csuoj1014】 西湖三人行

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

    题意

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

    Solution

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

    细节

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

    代码

    // csuoj1014
    #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
    ");
    		else printf("%d
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Git操作命令2-在Git仓库里管理文件历史-分支操作
    mvvmlight框架搭建VS版本不同导致的问题
    wpf命令详解
    wpf触发器
    wpf控件模型
    wpf中Interaction.Behaviors详解
    wpf附加属性详解
    wpf依赖属性概述
    wpf体系结构
    MySql5.7下载安装配置教程
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6048121.html
Copyright © 2011-2022 走看看