码迷,mamicode.com
首页 > 其他好文 > 详细

P1082丛林探险

时间:2015-10-26 18:43:18      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:

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

样例1

样例输入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

样例输出1

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 }

 

P1082丛林探险

标签:

原文地址:http://www.cnblogs.com/lidaxin/p/4911740.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!