http://acm.hdu.edu.cn/showproblem.php?pid=2992
题意:运输公司要从初始城市运送货物到目的城市,共有n个城市,编号是1~n。出发点和目的地分别是1和n号城市。在这些城市中有h个免费客栈,司机一天最多能走10小时,晚上选择一个客栈休息。给出h个客栈所在的城市以及m个城市的连接情况,问最少需要的客栈数。
思路:把h个客栈看做点,编号为1~h,起点标号为0,终点标号为h+1,这样共h+2个点。spfa求任两个客栈之间的路程,若 <= 600,则建边(注意建边建的是客栈的编号,而不是城市编号,用map映射),权值为1。最后求0到h+1的最短路。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
struct node
{
int u,v;
int w;
};
map <int, int> mp;
vector <struct node> edge[10010];
int n,m,num;
int a[110];
int graph[110][110]; //映射后的图
void init()
{
mp.clear();
for(int i = 1; i <= n; i++)
edge[i].clear();
for(int i = 0; i <= num+2; i++)
{
for(int j = 0; j <= num+2; j++)
{
if(i == j) graph[i][j] = 0;
else graph[i][j] = INF;
}
}
}
void spfa(int s)
{
queue <int> que;
int dis[10100];
int inque[10100];
while(!que.empty()) que.pop();
memset(dis,INF,sizeof(dis));
memset(inque,0,sizeof(inque));
dis[s] = 0;
inque[s] = 1;
que.push(s);
while(!que.empty())
{
int u = que.front();
que.pop();
inque[u] = 0;
for(int i = 0; i < (int)edge[u].size(); i++)
{
int v = edge[u][i].v;
if(dis[v] > dis[u] + edge[u][i].w)
{
dis[v] = dis[u] + edge[u][i].w;
if(!inque[v])
{
inque[v] = 1;
que.push(v);
}
}
}
}
for(int i = 1; i <= n; i++)
{
if(dis[i] <= 600)
graph[ mp[s] ][ mp[i] ] = 1;
}
}
void floyd() //求0到h+1的最短路
{
for(int k = 0; k <= num+1; k++)
{
for(int i = 0; i <= num+1; i++)
{
for(int j = 0; j <= num+1; j++)
{
if( graph[i][k] + graph[k][j] < graph[i][j])
graph[i][j] = graph[i][k] + graph[k][j];
}
}
}
}
int main()
{
while(~scanf("%d",&n) && n)
{
scanf("%d",&num);
init();
for(int i = 1; i <= num; i++)
{
scanf("%d",&a[i]);
mp[ a[i] ] = i;
}
mp[1] = 0;
mp[n] = num+1;
a[0] = 1;
a[num+1] = n;
scanf("%d",&m);
while(m--)
{
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
edge[u].push_back((struct node) {u,v,w});
edge[v].push_back((struct node) {v,u,w});
}
for(int i = 0; i <= num+1; i++)
spfa( a[i] );
floyd();
if(graph[0][num+1] < INF)
printf("%d\n",graph[0][num+1]-1);
else printf("-1\n");
}
return 0;
}