http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1318
题意:给一个无向图,起点,终点,和加油站所在的位置,邮箱容量,求最短璐。每到一个加油站就可以把油加满
这题确实没什么可说的,由于邮箱里的油最多跑2000公里,开个二维的就好了,dis[u][c]表示到u号结点,剩余油量还可以跑c公里时的最短路。
但是这题有个坑爹的地方:没有给点的数目,只知道边的数目是3000,如果开6000×2000的数组就会MLE,少开一点5000×2000的话就RE,当然也可能是我写渣了。
所以最后我是从起点先搜下看哪些点是可达的,然后把不可达的点删掉,这样就可以保证最多有3001个点了,这样数组就不会MLE了。。。
代码:
#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
#include<queue>
using namespace std;
const int maxm = 3001;
const int maxn = 3105;
const int INF = 0x3ffffff;
struct Side{
int to,next,w;
}side[maxm*2],side1[maxm*2];
int node1[maxn*2],top,top1,node[maxn];
void add_side(int u,int v,int w){
side[top]=(Side){v,node[u],w};node[u]=top++;
}
void add_side1(int u,int v,int w){
side1[top1]=(Side){v,node1[u],w};node1[u]=top1++;
side1[top1]=(Side){u,node1[v],w};node1[v]=top1++;
}
int cap;
map<string,int>city;
int cnt1,cnt,start,end;
bool is1[maxn],is[maxn];
int get_id(string str){
if(city.count(str)==0)city[str]=++cnt1;
return city[str];
}
int dis[maxn][2001];
bool inqueue[maxn][2001];
queue<pair<int,int> >q;
int get_dis(){
for(int i=1;i<=cnt;i++){
for(int j=0;j<=cap;j++){
inqueue[i][j]=false;
dis[i][j]=INF;
}
}
dis[start][cap]=0;
pair<int,int>tmp=make_pair(start,cap);
q.push(tmp);
while(!q.empty()){
tmp=q.front();q.pop();
int u=tmp.first;
int c=tmp.second;
inqueue[u][c]=false;
if(c!=cap&&is[u]){
if(dis[u][c]<dis[u][cap]){
dis[u][cap]=dis[u][c];
if(!inqueue[u][cap]){
inqueue[u][cap]=true;
q.push(make_pair(u,cap));
}
}
}
for(int i=node[u];i!=-1;i=side[i].next){
int v=side[i].to;
int last=c-side[i].w;
if(last<0)continue;
if(dis[u][c]+side[i].w<dis[v][last]){
dis[v][last]=dis[u][c]+side[i].w;
if(!inqueue[v][last]){
inqueue[v][last]=true;
q.push(make_pair(v,last));
}
}
}
}
int ans=INF;
for(int i=0;i<=cap;i++){
ans=min(ans,dis[end][i]);
}
return ans==INF?-1:ans;
}
bool vis[6001];
int id[maxn*2];
void dfs(int u){
for(int i=node1[u];i!=-1;i=side1[i].next){
int v=side1[i].to;
if(!vis[v]){
vis[v]=true;
dfs(v);
}
}
}
int main(){
int n,m;
while(~scanf("%d%d%d",&m,&n,&cap)){
if(m==0&&n==0&&cap==0)break;
cap=cap*10;
city.clear();
top=0;
cnt=0;
cnt1=0;
top1=0;
memset(node,-1,sizeof(node));
memset(node1,-1,sizeof(node1));
memset(is,false,sizeof(is));
memset(is1,false,sizeof(is1));
memset(vis,false,sizeof(vis));
string u,v;
cin>>u>>v;
start=get_id(u);
end=get_id(v);
for(int i=0;i<m;i++){
cin>>u>>v;
int w;
scanf("%d",&w);
int x=get_id(u);
int y=get_id(v);
add_side1(x,y,w);
}
for(int i=0;i<n;i++){
cin>>u;
is1[get_id(u)]=true;
}
vis[start]=true;
dfs(start);
if(!vis[end])printf("-1\n");
else{
for(int i=1;i<=cnt1;i++){
if(!vis[i])continue;
id[i]=++cnt;
}
for(int u=1;u<=cnt1;u++){
if(!vis[u])continue;
for(int i=node1[u];i!=-1;i=side1[i].next){
int v=side1[i].to;
if(!vis[v])continue;
add_side(id[u],id[v],side1[i].w);
}
}
for(int i=1;i<=cnt1;i++){
if(vis[i]&&is1[i])is[id[i]]=true;
}
start=id[start];
end=id[end];
printf("%d\n",get_dis());
}
}
}