运筹帷幄
(road.cpp)
【题目描述】
刘邦军行至迷糊林,见其中瘴气围绕,又有青狼猛虎之兽,难于前行。
已知迷糊林是一个共有n个结点的图,点与点之间共有m条道路相连接,每条路有参数t,c,分别表示行走于该路的时间以及兵士损失量。你已知道,刘邦除了脸皮厚什么都不会而且兵力少得可怜,所以需要在还能有兵士存活的情况下尽快走出迷糊林。
刘邦踞鞍而问曰:“子房,如之奈何?”。
【文件格式】
输入文件:第一行两个整数n,m,表示节点数以及边数。
以下m行每行4个整数u,v,c,t,表示u点以及v点之间有一条参数为c,t的边,c为兵士损失量,t为耗费时间。
第m+2行有两个整数s,t,表示起点与终点。
第m+3行有一个整数k,表示刘邦军的兵力。
输出文件:
一个整数表示能走出迷糊林的最短时间,如果不能走出请输出-1。
【样例数据】
Input(road.in)4 51 2 2 31 3 3 51 4 7 102 4 4 63 4 2 61 45Output (road.out)
11【数据约定】
n<=5000 ,m<=40000 , c,d<=300 , k<=10^9
[Hint]
本题数据随机生成。
【题目思路】
这个题主要是搜索,bfs,不过要是只用单纯的搜索的话绝对会超时,超的不止一点。。。。。所以我用了两种剪枝,第一是先spfa一遍图,算出每个点到终点的最短距离,如果当前搜到的点+这个点到终点的最短距离(士兵数)<拥有的士兵总量,直接过;第二是如果时间超过了当前存储的最小时间(迷糊林路的长度),直接过。
下面上代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; const int N = 40000+10; struct Edge { int v,b,t,next; }e[N*2]; int en=0,front[N]; int m,n,u,v,b,t; int qi,zhong; int liu; int d[40001]; void adde(int u,int v,int b,int t) { en++; e[en].v=v , e[en].b=b , e[en].t=t , e[en].next=front[u]; front[u]=en; } void spfa() { queue<int> q; bool inq[40001]; memset(inq,0,sizeof(inq)); for(int i=1;i<=m;i++) d[i]=1e9+1e9; d[zhong]=0;inq[zhong]=1; q.push(zhong); while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=false; for(int i=front[u];i;i=e[i].next) { Edge es=e[i]; int v=es.v; if(d[v]>d[u]+es.b) { d[v]=d[u]+es.b; if(!inq[v]) q.push(v) , inq[v]=1; } } } } bool dg[5001]; int bd=0,bt=0; int small=1e9; void dfs(int u,int blood,int dist) { if(u==zhong) { small=dist; return; } for(int i=front[u];i;i=e[i].next) { Edge es=e[i]; if(!dg[es.v] && blood-es.b > d[es.v] && dist + es.t < small) { dg[es.v]=1; dfs(es.v,blood-es.b,dist+es.t); dg[es.v]=0; } } } void read(int& x) { char c=getchar(); while(!isdigit(c)) c=getchar(); x=0; while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); } } int main() { freopen("road.in","r",stdin); freopen("road.out","w",stdout); read(m),read(n); //memset(dg,0,sizeof(dg)); for(int i=1;i<=n;i++) { read(u),read(v),read(b),read(t); adde(u,v,b,t); adde(v,u,b,t); } read(qi),read(zhong),read(liu); spfa(); if(d[qi] > liu) { cout<<"-1"; } else { dg[qi]=1; dfs(qi,liu,0); cout<<small; } return 0; }数据:http://files.cnblogs.com/files/zhangone/road.zip
(以上代码数据中十个点全过)
感谢李学长在我各种蒟蒻的时候耐心讲解。
时间: 2024-10-25 01:53:54