描述 Description | |||
东非大裂谷中有一片神秘的丛林,是全世界探险家的乐园,著名黄皮肤探险家BB一直想去试试。正好我国科学家2005年4月将首次对东非大裂谷进行科考,BB决定随科考队去神秘丛林探险。在出发之前,他搜集了国内外有关神秘丛林探险的资料,并绘制成一张地图:该地图上有若干安全点(包括入口点和出口点),并将这些安全点编号为1、2、…、n;如果一个安全点和另一个安全点有一条路直接相通,则用一条边标示;该图是一个连通图(任意两点间有至少一条路径),地图上每条路的长度和走这条路需要耗费的体力都做了标示。 KK行走速度为1,并知道自己体力为K。他想知道根据自己的体力情况能否成功地穿过丛林。 | |||
输入格式 Input Format | |||
第一行两个整数n(<=5000) m(<=40000),分别表示地图上安全点的个数和边的数目; 第2行至第m+1 行每行4个整数x y c d,x、y表示有直接相联边的两个点的编号,c走这条路需要耗费的体力;d表示边的长度;(其中150<=c,d<=300) 第m+2行两个整数s t,分别表示安全的入口点和出口点的编号; 第m+3行一个整数k,表示BB的体力值;(K<10^9) 同一行上的多个数据用空格隔开。 | |||
输出格式 Output Format | |||
一个整数,如果BB能安全地从如入口穿过丛林到达出口,输出最短时间,否则输出-1 | |||
样例输入 Sample Input | |||
样例输出 Sample Output | |||
时间限制 Time Limitation | |||
各个测试点1s |
有人用最短路做出来了,应该是数据弱了的原因。他们的方法是比较的时候先比较长度,再比较体力,实际上有反例。
因为一开始体力没超过限制的时候,就会尽量先满足长度最短而使体力变大,可能导致最后体力超过限制。实际上一开始为了保证能到达,不一定选择路径最短。
搜索是可以的,加个最优化剪枝就能过。
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
using std::sort;
long s,t,k;
long ans = 0x3f3f3f3f;
long long dist[5010];
bool used[5010];
long que[2000010];
const long qmod = 2000000;
/*struct node
{
long ind;
long strenth;
long length;
node* nxt;
};
node* head[5010];
*/
struct Edge
{
long u;
long v;
long strenth;
long length;
bool operator<(const Edge& e2)const
{
return u < e2.u;
}
};
Edge edge[80010];
long start[5010];
long getint()
{
long rs=0;bool sgn=1;char tmp;
do tmp = getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp == '-'){tmp=getchar();sgn=0;}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
void spfa1()
{
memset(dist,0x3f,sizeof dist);
dist[s] = 0;
long l = 0;
long r = 0;
que[++r] = s;
long u ,v;
while (l < r)
{
l ++;
if (l == qmod)
l = 0;
u = que[l];
used[u] = false;
for (long vv=start[u];edge[vv].u==u;vv++)
{
v = edge[vv].v;
if (dist[v]>dist[u]+edge[vv].strenth)
{
dist[v] = dist[u] + edge[vv].strenth;
if (!used[v])
{
used[v] = true;
r ++;
if (r == qmod)
r = 0;
que[r] = v;
}
}
}
}
}
void dfs(long u,long ss,long sl)
{
if (sl >= ans)
{
return;
}
if (u == t)
{
if (ans > sl)
ans = sl;
return;
}
for (long vv=start[u];edge[vv].u==u;vv++)
{
long v = edge[vv].v;
if (!used[v] && ss+edge[vv].strenth<=k)
{
used[v] = true;
dfs(v,ss+edge[vv].strenth,sl+edge[vv].length);
used[v] = false;
}
}
}
/*
void insert(long a,long b,long c,long d)
{
node* nn = new node;
nn -> ind = b;
nn -> nxt = head[a];
nn -> strenth = c;
nn -> length = d;
head[a] = nn;
nn = new node;
nn -> ind = a;
nn -> nxt = head[b];
nn -> strenth = c;
nn -> length = d;
head[b] = nn;
}
*/
int main()
{
freopen("forest.in","r",stdin);
freopen("forest.out","w",stdout);
long n = getint();
long m = getint();
for (long i=0;i<m;i++)
{
edge[i*2+1].u = edge[i*2+2].v = getint();
edge[i*2+1].v = edge[i*2+2].u = getint();
edge[i*2+1].strenth = edge[i*2+2].strenth = getint();
edge[i*2+1].length = edge[i*2+2].length = getint();
}
m <<= 1;
sort(edge+1,edge+m+1);
for (long i=1;i<m+1;i++)
{
if (!start[edge[i].u])
{
start[edge[i].u] = i;
}
}
s = getint();
t = getint();
k = getint();
spfa1();
if (dist[t] > k)
{
printf("-1");
return 0;
}
used[s] = true;
dfs(s,0,0);
printf("%ld",ans);
return 0;
}
二分版本
#include <cstdio>
#include <string>
#include <cstring>
long s,t,k;
long n;
long mid;
bool used[5010];
struct node
{
long ind;
node* nxt;
long c;
long d;
};
node* head[5010];
long getint()
{
long rs=0;bool sgn=1;char tmp;
do tmp=getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){tmp=getchar();sgn=0;}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
void insert(long a,long b,long c,long d)
{
node* nn = new node;
nn -> ind = b;
nn -> nxt = head[a];
nn -> c = c;
nn -> d = d;
head[a] = nn;
}
bool can(long u,long e,long s)
{
if (s > mid)
return false;
if (u == t)
{
if (mid > s)
mid = s;
return true;
}
for (node* vv=head[u];vv;vv=vv->nxt)
{
long v = vv->ind;
if (!used[v])
{
if (e-vv->c >= 0)
{
used[v] = true;
if (can(v,e-vv->c,s+vv->d))
return true;
used[v] = false;
}
}
}
return false;
}
int main()
{
freopen("forest.in","r",stdin);
freopen("forest.out","w",stdout);
n = getint();
long m = getint();
long sumd = 0;
for (long i=1;i<m+1;i++)
{
long x = getint();
long y = getint();
long c = getint();
long d = getint();
insert(x,y,c,d);
insert(y,x,c,d);
sumd += d;
}
s = getint();
t = getint();
k = getint();
long ans = 0x3f3f3f3f;
long l = 0;
long r = sumd;
while (l <= r)
{
mid = (l+r)>>1;
memset(used,0,sizeof used);
used[s] = true;
if (can(s,k,0))
{
if (ans > mid)
ans = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
if (ans == 0x3f3f3f3f)
printf("-1");
else
printf("%ld",ans);
return 0 ;
}