分道扬镳 /// 邻接表 DFS 剪枝 oj1332

题目大意:

编号为1…N 的N个城市之间以单向路连接,每一条道路有两个参数:路的长度和通过这条路需付的费用。

Bob和Alice生活在城市1,但是当Bob发现了Alice玩扑克时欺骗他之后,他决定与她翻脸,离开城市1前往城市N。Bob想尽快到达城市N,但是他的钱不多。

希望你帮助Bob找到一条从城市1到城市N的总费用不超过Bob的承受能力的最短路径。

Input

输入的第一行是3个整数 K, N, R ,其中:

    K:表示Bob能承受的最大费用,0 ≤ K ≤ 10000

    N:表示城市的总数,2 ≤ N ≤ 100

    R:表示道路的条数,1 ≤ R ≤ 10000

接下来的R行,每行用S  D  L  T(以空格隔开)表示一条道路:

    S:表示道路的出发城市,1 ≤ S ≤ N

    D:表示道路的目标城市,1 ≤ D ≤ N

    L:表示道路的长度,1 ≤ L ≤ 100

    T:表示通过这条道路需付的费用,0 ≤ T ≤ 100

Output

为每个测试用例输出一行结果:总费用小于或等于最大费用K的最短路径的长度。如果这样的路径不存在,则仅仅输出 -1 。

Sample Input

5 6 7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2

Sample Output

11

Hint

测试数据的图中可能有重边、有自环

 
原本天真地以为邻接表+DFS+简单剪枝就能过 结果还是TLE
之前看题解发现了一个 特殊的剪枝 用上就AC了
 
 minlen[node][fee]数组记录1~ node 点在 fee 花费时的最短距离
假如搜索到 i 点而花费为 fe 时 le 超过了已记录到的 minlen[i][fe] 则可结束本次搜索
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;

int s[10005],d[10005],l[10005],t[10005],flag[105];
int k,n,r,len,minlen[105][10005],first[105],nexti[10005];

void DFS(int i,int le,int fe)
{
    if(fe>k || le>minlen[i][fe] || le>len) return;
 /// 用minlen数组记下 i 点在 fe 花费时的最短距离,若超过则可停止继续搜索了

    if(i==n)
    {
        len=min(len,le);
        //printf("%d
",len);
        return ;
    }
    else
    {
        if(le<minlen[i][fe]) /// 若存在更短的距离 则更新minlen的值
            for(int j=fe;j<=k;j++) 
                minlen[i][j]=le;

        int in=first[i];
        while(in!=-1)
        {
            if(!flag[d[in]])
            {
                flag[d[in]]=1; /// 避免自环情况
                DFS(d[in],le+l[in],fe+t[in]);
                flag[d[in]]=0;
            }
            in=nexti[in];
        } /// 邻接表遍历

    }

}
int main()
{
    while(~scanf("%d%d%d",&k,&n,&r))
    {
        memset(flag,0,sizeof(flag));
        for(int i=1;i<101;i++)
            for(int j=0;j<10001;j++)
                minlen[i][j]=200000;
        memset(first,-1,sizeof(first));

        for(int i=1;i<=r;i++)
        {
            scanf("%d%d%d%d",&s[i],&d[i],&l[i],&t[i]);
            nexti[i]=first[s[i]];
            first[s[i]]=i;
        } /// 建邻接表 可避免重边引起的错误

        flag[1]=1; len=INF;
        DFS(1,0,0);

        if(len==INF) printf("-1
");
        else printf("%d
",len);
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zquzjx/p/8605948.html