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;
}