Single Round Match 479 Round 1 - Division I, Level Two TheAirTripDivOne

这种题目让最小值最大,一般就是二分答案。TC的题目总是不那么明显。我一开始认为二分是错的。但是虽然航班出发时间被分成一段一段的,但是等的时间少总能坐上等的时间长能做的航班,大不了多等一会儿。那么就是二分答案加最短路了。

#include <bits/stdc++.h>
#define maxn 1009
using namespace std;
typedef long long LL;
const LL INF=1e17;
char S[100009];
bool inq[maxn];
LL d[maxn];
int n,mx;
struct Edge
{
	int v,f,t,p;
	Edge(int _v,int _f,int _t,int _p)
	{
		v=_v;f=_f;t=_t;p=_p;
	}
};
vector<Edge>G[maxn];
LL solve(LL cur,LL f,LL p)
{
	if(cur<=f)
		return f-cur;
	else
	{
		cur%=p;
		f%=p;
		if(cur<=f)
			return f-cur;
		else
			return f-cur+p;
	}
}
bool spfa(LL mid)
{
	for(int i=1;i<=n;i++) d[i]=INF;
	queue<int>Q;
	d[1]=0;
	Q.push(1);
	while(!Q.empty())
	{
		int u=Q.front();Q.pop();
		inq[u]=0;
		for(int i=0;i<(int)G[u].size();i++)
		{
			int v=G[u][i].v;
			LL t=d[u];
			if(u==1)
				t++;
			else
				t+=mid;
			LL T=solve(t,G[u][i].f,G[u][i].p);
			//printf("%d %lld\n",u,t+T);
			if(G[u][i].t+T+t>mx)
				continue;
			if(d[v]>t+G[u][i].t+T)
			{
				d[v]=t+G[u][i].t+T;
				if(!inq[v])
				{
					inq[v]=1;
					Q.push(v);
				}
			}
		}
	}
	return d[n]<=mx;
}
class TheAirTripDivOne
{
public:int find(int N, vector <string> flights, int time)
	{
		n=N;
		mx=time;
		int len=0;
		for(int i=0;i<(int)flights.size();i++)
			for(int j=0;j<(int)flights[i].length();j++)
				S[len++]=flights[i][j];
		char *p=strtok(S," ");
		while(p)
		{
			int last=0,cur=0,a,b,f,t,P;
			for(;p[cur]!=',';cur++);
			p[cur]=0;a=atoi(p+last);p[cur]=',';last=++cur;
			for(;p[cur]!=',';cur++);
			p[cur]=0;b=atoi(p+last);p[cur]=',';last=++cur;
			for(;p[cur]!=',';cur++);
			p[cur]=0;f=atoi(p+last);p[cur]=',';last=++cur;
			for(;p[cur]!=',';cur++);
			p[cur]=0;t=atoi(p+last);p[cur]=',';last=++cur;
			P=atoi(p+last);
			G[a].push_back(Edge(b,f,t,P));
			//printf("%d %d %d %d %d\n",a,b,f,t,P);
			p=strtok(NULL," ");
		}
		LL L=1,R=1e9;
		if(!spfa(L))
			return -1;
		while(L<R)
		{
			LL M=(L+R+1)>>1;
			if(spfa(M))
				L=M;
			else
				R=M-1;
		}
		return L;
	}
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值