Aizu 1318 Long Distance Taxi 最短路

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章