美团CodeM2018资格赛赛题官方版本详解(五)——你的城市

解题思路


标准程序

#include<cstdio>
#include<cstdlib>
#include<string>
#include<algorithm>

#define For(i,l,r) for(int i=l;i<=r;i++)
#define Dor(i,r,l) for(int i=r;i>=l;i--)
#define timeMagicNumber 49
#define inf 100000000

using namespace std;

char convert_buffer[10];
int convert(char* buffer){
	int a,b;
	sscanf(buffer,"%d:%d",&a,&b);
	return a*2 + b / 30;
}
char* convert(int num){
	sprintf(convert_buffer, "%d:%02d", num/2, (num&1)*30);
	return convert_buffer;
}

struct Edge{
	int x,y,co,s,t;
	void read(){
		scanf("%d%d%d",&x,&y,&co);
		scanf("%s",convert_buffer); s = convert(convert_buffer);
		scanf("%s",convert_buffer); t = convert(convert_buffer);
	}
}E[200005];

int n,m;
int cnt;
int son[200005],Next[500005],ed[500005],edge_cost[500005],edge_s[500005],edge_t[500005];

void graph_link(int x,int y,int c,int s,int t){
	Next[++cnt] = son[x]; son[x]=cnt; ed[cnt]=y;
	edge_cost[cnt] = c; edge_s[cnt] = s; edge_t[cnt] = t;
}

int f[2005][55],ff[200005];
int dist[2005][55];

int dfs(int u,int ut){
	if (f[u][ut] == 1) return 1;
	if (f[u][ut] == 0) return 0;
	if (ut == timeMagicNumber) return 0;

	f[u][ut] = 0;
	for(int i=son[u];i;i=Next[i])
	if(edge_s[i] == ut){
		f[u][ut] |= dfs(ed[i],edge_t[i]+1);
	}
	f[u][ut] |= dfs(u,ut+1);

	return f[u][ut];
}

void dfs(int u,int ut,int di){
	if (di >= dist[u][ut]) return;
	dist[u][ut] = di;
	if (u == n) return;
	if (ut == timeMagicNumber) return;
	if (ut >= ff[u]) return;

	dfs(u,ut+1,di);
	for(int i=son[u];i;i=Next[i])
	if(edge_s[i] == ut){
		dfs(ed[i],edge_t[i]+1,edge_cost[i]+di);
	}
}

int main(){
	scanf("%d%d",&n,&m);
	For(i,1,m) E[i].read();
	For(i,1,m) graph_link(E[i].x,E[i].y,E[i].co,E[i].s,E[i].t);

	For(i,1,n-1) For(t,0,timeMagicNumber) f[i][t] = -1,f[n][t] = 1;
	For(i,1,n-1) For(t,0,timeMagicNumber-1) dfs(i,t);

	For(i,1,n) For(t,0,timeMagicNumber) if(f[i][t] == 1) ff[i] = t;

	For(i,1,n) For(t,0,timeMagicNumber) dist[i][t] = inf;
	dfs(1,0,0);

	int ans = inf;
	For(nt,0,timeMagicNumber) ans = min(ans,dist[n][nt]);
	if (ans == inf) ans = -1;
	printf("%d\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值