poj 1724 ROADS(dfs)

http://poj.org/problem?id=1724


大致题意:N个城市由R条单向路连通,每条路(S,D)之间有两个因素:路的长度L和路的花费T。现要从城市1到达城市N,求花费在K以内的最短路程。


思路:很明显的dfs(他们都说很明显的spfa。。。)。不过dfs有几点注意的地方:

建立邻接表不能用vector存,要用链表的形式,采用头插法。

dfs的时候,在递归节点v之前,要先预判断一下到达v之后总花费是否大于k,若大于K就跳过,不必再调用v节点,这样会省很多时间。对于路程的处理也同样提前先判断一下。

63ms

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#define LL long long
#define _LL __int64
#define eps 1e-8
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 110;

struct node
{
	int v,l,t;
	struct node *next;
}edge[maxn];

int n,m,k;
int vis[maxn];
int ans;

void dfs(int u, int cost, int len)
{
	/*
	注意不要在这里判断,要在递归前先判断。
	if(cost > k)
		return;
	if(u == n )
	{
		ans = min(ans,len);
		return;
	}
	*/
	
	for(struct node *tmp = edge[u].next; tmp!= NULL; tmp = tmp->next)
	{
		int v = tmp->v;
		if(!vis[v] && cost + tmp->t <= k && (len + tmp->l < ans || ans == -1)) //重点:提前判断
		{
			if(v == n)
			{
				ans = len + tmp->l;
				continue;
			}
			vis[v] = 1;
			dfs(v, cost + tmp->t, len + tmp->l);
			vis[v] = 0;
		}
	}
}

int main()
{
	int s,d,l,t;

	while(~scanf("%d %d %d",&k,&n,&m))
	{
		for(int i = 1; i <= n; i++)
			edge[i].next = NULL;

		for(int i = 1; i <= m; i++)
		{
			scanf("%d %d %d %d",&s,&d,&l,&t);
			struct node *tmp = (struct node *)malloc(sizeof(struct node));
			tmp->v = d;
			tmp->l = l;
			tmp->t = t;
			tmp->next = edge[s].next;
			edge[s].next = tmp;
		}

		ans = INF;
		memset(vis,0,sizeof(vis));
		vis[1] = 1;
		dfs(1,0,0);

		if(ans == INF)
			printf("-1\n");
		else printf("%d\n",ans);
	}
	return 0;
}

二维spfa,远没有dfs快啊,329ms.


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#define LL long long
#define _LL __int64
#define eps 1e-8
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 110;
const int maxm = 10010;

struct node
{
	int v,l,t;
	int next;
}edge[maxm];
int cnt,head[maxn];
int n,m,k;
int dis[maxn][maxm+10];
int inque[maxn];

void init()
{
	cnt = 0;
	memset(head,-1,sizeof(head));
}

void add(int u, int v, int l,int t)
{
	edge[cnt] = (struct node){v,l,t,head[u]};
	head[u] = cnt++;
}

void spfa()
{
	queue <int> que;
	while(!que.empty()) que.pop();
	memset(inque,0,sizeof(inque));
	for(int j = 0; j <= k; j++)
		dis[1][j] = 0;
	for(int i = 2; i <= n; i++)
	{
		for(int j = 0; j <= k; j++)
			dis[i][j] = INF;
	}

	inque[1] = 1;
	que.push(1);

	while(!que.empty())
	{
		int u = que.front();
		que.pop();
		inque[u] = 0;

		for(int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].v;
			for(int j = edge[i].t; j <= k; j++)
			{
				if(dis[v][j] > dis[u][j-edge[i].t] + edge[i].l)
				{
					dis[v][j] = dis[u][j-edge[i].t] + edge[i].l;
					if(!inque[v])
					{
						inque[v] = 1;
						que.push(v);
					}
				}
			}
		}
	}
}

int main()
{
	int s,d,l,t;
	while(~scanf("%d %d %d",&k,&n,&m))
	{
		init();
		for(int i = 0; i < m; i++)
		{
			scanf("%d %d %d %d",&s,&d,&l,&t);
			add(s,d,l,t);
		}

		spfa();
		int ans = INF;
		for(int i = 0; i <= k; i++)
		{
			if(dis[n][i] < ans)
				ans = dis[n][i];
		}
		if(ans == INF)
			printf("-1\n");
		else printf("%d\n",ans);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值