列表

详情


NC51306. 最优高铁环

描述

幻影国建成了当今世界上最先进的高铁,该国高铁分为以下几类:
  • S---高速光子动力列车---时速1000km/h 
  • G---高速动车---时速500km/h 
  • D---动车组---时速300km/h 
  • T---特快---时速200km/h 
  • K---快速---时速150km/h 
该国列车车次标号由上述字母开头,后面跟着一个正整数构成。 
由于该国地形起伏不平,各地铁路的适宜运行速度不同。因此该国的每一条行车路线都由K列车次构成。例如: K=5的一条路线为:T120-D135-S1-G12-K856。当某一条路线的末尾车次与另一条路线的开头车次相同时, 这两条路线可以连接起来变为一条更长的行车路线。显然若干条路线连接起来有可能构成一个环。
若有3条行车路线分别为:
x_1-x_2-x_3
x_3-x_4
x_4-x_5-x_1
车次的速度分别为
定义高铁环的值为(环上各条行车路线速度和)的平均值,即:

所有高铁环的值的最大值称为最优高铁环的值。
给出M条行车路线,求最优高铁环的值。

输入描述

第一行为行车路线条数M
接下来M行每行一条行车路线,由若干车次构成,各车次之间用'-'号隔开,车次的标号方式如上所述。
数据保证输入的合法性。

输出描述

最优高铁环的值。四舍五入到最接近的整数。
若不存在这样的环,输出-1.

示例1

输入:

3
T120-D135-S1
S1-G12
G12-K856-T120 

输出:

1283

说明:

[(200+300+1000)+(1000+500)+(500+150+200)]/3=1283

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 54ms, 内存消耗: 2040K, 提交时间: 2022-08-21 10:37:02

#include<bits/stdc++.h>
using namespace std;
#define rg register
#define il inline
#define co const
typedef long long ll;
co int N=5e4+1;
co double eps=1e-3;
int n,m,st,ed,t;
int head[N],edge[N],nt[N],tot;
double d[N],s[N],leng[N];
bool v[N];
 
il void add(int x,int y){
    edge[++tot]=y,nt[tot]=head[x],head[x]=tot;
}
il int f(char ch){
    switch(ch){
        case 'S': t=0;return 1000;
        case 'G': t=1;return 500;
        case 'D': t=2;return 300;
        case 'T': t=3;return 200;
        case 'K': t=4;return 150;
    }
    return -1;
}
bool dfs(int x){
    v[x]=1;
    for(int i=head[x];i;i=nt[i]){
        int y=edge[i];double z=leng[i];
        if(d[y]>d[x]+z){
            d[y]=d[x]+z;
            if(v[y]||dfs(y)) return 1;
        }
    }
    v[x]=0;
    return 0;
}
bool pd(double x){
    for(int i=1;i<=m;++i) leng[i]=x-s[i];
    memset(v,0,sizeof v);
    memset(d,0x3f,sizeof d);
    for(int i=1;i<N;++i)
        if(dfs(i)) return 1;
    return 0;
}
int main(){
    cin>>m;
    for(int i=1;i<=m;++i){
        static char str[150];
        scanf("%s",str),n=strlen(str);
        int x=0;
        bool flag=0;
        for(int j=0;j<n;++j){
            if(isdigit(str[j])) x=x*10+str[j]-'0';
            else if(str[j]=='-'){
                if(!flag) st=x+t*10000;
                flag=1;
                x=0;
            }
            else s[i]+=f(str[j]);
        }
        ed=x+t*10000;
        add(st,ed);
    }
    double l=0,r=0x7fffffff,ans=-1;
    while(r-l>eps){
        double mid=(l+r)/2;
        if(pd(mid)) l=ans=mid;
        else r=mid;
    }
    printf("%.0lf\n",ans);
    return 0;
}

C++ 解法, 执行用时: 104ms, 内存消耗: 2484K, 提交时间: 2021-09-01 16:05:51

#include<bits/stdc++.h>

using namespace std;

const int N=1e5+90;
const double eps=1e-3;

int n;
map<string,int> M;
int cnt;
int cnte,ver[N],nxt[N],head[N];
double l,r;
int we[N];
double dis[N],edge[N];

int get_point(string a){
	if(M.find(a)!=M.end()) return M[a];
	return M[a]=++cnt;
}

int f(char ch){
	switch (ch)
	{
		case 'S': return 1000;
		case 'G': return 500;
		case 'D': return 300;
		case 'T': return 200;
		default : return 150;
	}
	return -1;
}

void add(int a,int b,double c){
	nxt[++cnte]=head[a],head[a]=cnte,ver[cnte]=b,edge[cnte]=c;
}

void read(string a){
	int len=a.size();
	int i=0,fl=0,x=0,y=0;double v=0;
	while(i<len)
	{
		string temp="";
		while(i<len&&a[i]!='-') temp+=a[i++];
		i++;
		if(!fl) x=y=get_point(temp);
		fl=1;
		if(i==len+1) y=get_point(temp);
		v+=f(temp[0]);
	}
	add(x,y,v);
	r+=v;
}

bool dfs(int i,double mid){
	we[i]=1;
	for(int io=head[i];io;io=nxt[io])
	{
		int v=ver[io];
		if(dis[v]>dis[i]+mid-edge[io])
		{
			dis[v]=dis[i]+mid-edge[io];
			if(we[v]||dfs(v,mid)) return true;
		}
	}
	we[i]=0;
	return false;
}

bool check(double mid){
	memset(we,0,sizeof we);
	memset(dis,0x3f,sizeof dis);
	for(int i=1;i<=cnt;i++)
		if(dfs(i,mid)) return true;
	return false;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		string a;
		cin>>a;
		read(a);
	}
	double as=-1;
	while(l+eps<r)
	{
		double mid=(l+r)/2;
		if(check(mid)) l=as=mid;
		else r=mid;
	}
	printf("%.0lf",as);
	
	return 0;
}

上一题