标签:
P1082丛林探险
东非大裂谷中有一片神秘的丛林,是全世界探险家的乐园,著名黄皮肤探险家BB一直想去试试。正好我国科学家2005年4月将首次对东非大裂谷进行科考,BB决定随科考队去神秘丛林探险。在出发之前,他搜集了国内外有关神秘丛林探险的资料,并绘制成一张地图:该地图上有若干安全点(包括入口点和出口点),并将这些安全点编号为1、2、…、n;如果一个安全点和另一个安全点有一条路直接相通,则用一条边标示;该图是一个连通图(任意两点间有至少一条路径),地图上每条路的长度和走这条路需要耗费的体力都做了标示。
KK行走速度为1,并知道自己体力为K。他想知道根据自己的体力情况能否成功地穿过丛林。
第一行两个整数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)
同一行上的多个数据用空格隔开。
一个整数,如果BB能安全地从如入口穿过丛林到达出口,输出最短时间,否则输出-1
4 5
1 2 2 3
1 3 3 5
1 4 7 10
2 4 4 6
3 4 2 6
1 4
5
11
各个测试点1s
【思路】
搜索+剪枝。
n+m=45000,可以考虑搜索st之间的每一条路径,选择最短的一条。
剪枝:
最优性剪枝:如果dist>ans则剪枝。
可行性剪枝:[最短路]预处理出点u到t的最小体力耗费d[u],如果Blood<d[u]则剪枝。
需要注意的是方案的不可行最好在枚举v的时候判断,否则的话:我试了一下,一个TLE一个WA。(这个WA也是很奇妙的=-=)
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 6 const int maxn = 5000+10 , maxm=40000+10; 7 const int INF=1<<30; 8 struct Edge{ 9 int v,c,d,next; 10 }e[2*maxm]; 11 int en=-1, front[maxn]; 12 13 int n,m,K; 14 15 inline void AddEdge(int u,int v,int c,int d) { 16 en++; e[en].v=v; e[en].c=c; e[en].d=d; e[en].next=front[u]; front[u]=en; 17 } 18 int d[maxn]; 19 void SPFA(int s) { 20 int inq[maxn]; 21 queue<int> q; 22 memset(inq,0,sizeof(inq)); 23 for(int i=1;i<=n;i++) d[i]=INF; 24 25 d[s]=0; inq[s]=1; q.push(s); 26 while(!q.empty()) { 27 int u=q.front(); q.pop(); inq[u]=0; 28 for(int i=front[u];i>=0;i=e[i].next) { 29 int v=e[i].v,w=e[i].c; 30 if(d[v]>d[u]+w) { 31 d[v]=d[u]+w; 32 if(!inq[v]) { 33 inq[v]=1; 34 q.push(v); 35 } 36 } 37 } 38 } 39 } 40 41 int ans=INF; 42 int vis[maxn]; 43 int s,t; 44 void dfs(int u,int Blood,int dist) { 45 if(u==t) { ans=dist; return; } 46 for(int i=front[u];i>=0;i=e[i].next){ 47 int v=e[i].v; 48 if(vis[v]) continue; 49 if(dist+e[i].d>=ans || Blood-e[i].c<d[v]) continue; 50 vis[v]=1; 51 dfs(v,Blood-e[i].c,dist+e[i].d); 52 vis[v]=0; 53 } 54 } 55 int main() { 56 memset(front,-1,sizeof(front)); 57 scanf("%d%d",&n,&m); 58 int u,v,c,f; 59 for(int i=0;i<m;i++) { 60 scanf("%d%d%d%d",&u,&v,&c,&f); 61 AddEdge(u,v,c,f); 62 AddEdge(v,u,c,f); 63 } 64 scanf("%d%d%d",&s,&t,&K); 65 SPFA(t); 66 if(d[s]>K) printf("-1\n"); 67 else 68 { 69 vis[s]=1; 70 dfs(s,K,0); 71 vis[s]=0; 72 printf("%d\n",ans); 73 } 74 return 0; 75 }
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/4911740.html