POJ 1724--ROADS

本文介绍了一种解决特定图论问题的方法:在给定的城市网络中寻找一条从起点到终点的路径,在路径花费不超过预设限制的情况下,使得路径长度最短。文章通过两种方法——深度优先搜索(DFS)和广度优先搜索(BFS),详细阐述了如何有效地解决问题,并给出了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有N个城市,R条路,每条路有花费和长度两个特性,求从城市1到城市N的花费不超过K的最短路。

题解:

  1. 易知最佳路径是不可能有环路的,所以使用最基本DFS,加入访问标记数组即可。
  2. BFS,利用二维状态数组dp[i][j]记录到第i城市花费j的最短路径,当这个值更新时,利用其不断更新其他城市的状态。

DFS:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define INF 0X7FFFFFFF

class node
{
public:
    int adjx;
    int len;
    int toll;
    node* next;
};

class adjList
{
public:
    node** adj;
    adjList(int n):adj(new node*[n])
    {
        memset(adj,0,sizeof(node*)*(n));
    }
    int adjInsert(int nodeNo,int adjx,int len,int toll)
    {
        node* newNode = new node;
        newNode->adjx = adjx;
        newNode->len = len;
        newNode->toll = toll;
        newNode->next = adj[nodeNo];
        adj[nodeNo] = newNode;
        return 0;
    }
};

class solve
{
private:
    int K,N,R;
    char* vis;
    adjList* g;
    int minLen;
public:
    solve(int k,int n,int r):K(k),N(n),R(r),minLen(INF)
    {
        g = new adjList(N+1);
        vis = new char[N+1];
        memset(vis,0,sizeof(char)*(N+1));
        processIn();
        DFS(1,0,0);
        printf("%d\n",minLen == INF?-1:minLen);
    }
    ~solve()
    {
        delete[] g;
        delete[] vis;
    }
    int processIn();
    int DFS(int u,int len,int cost);
};

int solve::DFS(int u,int len,int cost)
{
    vis[u] = 1;
    if(u == N)
    {
        if(cost <= K&&len < minLen)
        {
            minLen = len;
        }
        return 0;
    }
    if(len >= minLen||cost > K)
        return 0;
    int v;
    node* tmpNode;
    for(tmpNode = g->adj[u];tmpNode != NULL;tmpNode = tmpNode->next)
    {
        v = tmpNode->adjx;
        if(!vis[v])
        {
            DFS(v,len+tmpNode->len,cost+tmpNode->toll);
            vis[v] = 0;
        }
    }
    return 0;
}

int solve::processIn()
{
    int s,d,l,t;
    while(R--)
    {
        scanf("%d%d%d%d",&s,&d,&l,&t);
        g->adjInsert(s,d,l,t);
    }
    return 0;
}

int main()
{
    int k,n,r;
    while(~scanf("%d%d%d",&k,&n,&r))
    {
        solve poj_1724(k,n,r);
    }
    return 0;
}

BFS:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0X7F7F7F7F

class node
{
public:
    short adjx;
    short len;
    short toll;
    node* next;
};

class adjList
{
public:
    node** adj;
    adjList(int n):adj(new node*[n])
    {
        memset(adj,0,sizeof(node*)*(n));
    }
    int adjInsert(int nodeNo,int adjx,int len,int toll)
    {
        node* newNode = new node;
        newNode->adjx = adjx;
        newNode->len = len;
        newNode->toll = toll;
        newNode->next = adj[nodeNo];
        adj[nodeNo] = newNode;
        return 0;
    }
};

class solve
{
private:
    int K,N,R;
    adjList* g;
    int minLen;
    int totToll;
    short** dp;
public:
    solve(int k,int n,int r):K(k),N(n),R(r),minLen(INF),totToll(0)
    {
        g = new adjList(N+1);
        processIn();
        BFS();
        printf("%d\n",minLen == INF?-1:minLen);
    }
    ~solve()
    {
        delete[] g;
        delete[] dp;
    }
    int processIn();
    int BFS();
};

class queueNode
{
public:
    int nodeNo;
    short cost;
};

int solve::BFS()
{
    int i;
    queueNode now,next;
    totToll = min(totToll,K);
    dp = new short*[N+1];
    for(i = 1;i <= N;i++)
    {
        dp[i] = new short[totToll+1];
        memset(dp[i],0X7F,sizeof(short)*(totToll+1));
    }
    queue<queueNode> q;
    now.nodeNo = 1;
    now.cost = 0;
    dp[1][0] = 0;
    q.push(now);
    while(!q.empty())
    {
        now = q.front();
        q.pop();
        if(dp[now.nodeNo][now.cost] >= minLen)
        {
            continue;
        }
        if(now.nodeNo == N)
        {
            if(minLen > dp[N][now.cost])
            {
                minLen = dp[N][now.cost];
            }
            continue;
        }
        for(node* tmpNode = g->adj[now.nodeNo];tmpNode != NULL;tmpNode = tmpNode->next)
        {
            next.nodeNo = tmpNode->adjx;
            next.cost = tmpNode->toll+now.cost;
            if(next.nodeNo != 1&&next.cost <= totToll&&dp[next.nodeNo][next.cost] > tmpNode->len+dp[now.nodeNo][now.cost])
            {
                q.push(next);
                dp[next.nodeNo][next.cost] = tmpNode->len+dp[now.nodeNo][now.cost];
            }
        }
    }
    return 0;
}

int solve::processIn()
{
    int s,d,l,t;
    while(R--)
    {
        scanf("%d%d%d%d",&s,&d,&l,&t);
        g->adjInsert(s,d,l,t);
        totToll += t;
    }
    return 0;
}

int main()
{
    int k,n,r;
    while(~scanf("%d%d%d",&k,&n,&r))
    {
        solve poj_1724(k,n,r);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值