hdu4725 The Shortest Path in Nya Graph

这道题看了下很多人都是把每一层拆成两个点然后建图做的。

我的思路很直接,也不用建图,直接在更新每个点时更新他相邻的边和相邻的层,当然前提是每个点只更新一次,每个层也只更新一次,这样才能确保时间复杂度。

这里我用了两个邻接表,一个是邻接边,一个是邻接层,最后用优先队列优化下。

下面是代码

#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
const int M=2*111111;
int fir[M],u[M],v[M],w[M],nxt[M],e;//边的邻接
int n,m,c;
int lfir[M],lu[M],lnxt[M],le;//层的邻接
int lay[M];//表示每个点所在的层
int dis[M],vis[M];//dis表示与起点距离,vis标记边是否访问过
int lvis[M];//表示层是否访问过
struct cmp
{
bool operator()(int a,int b)
{
return dis[a]>dis[b];
}
}; priority_queue<int,vector<int>,cmp>Q;
void linsert(int la,int num)//插入层
{
lu[le]=num;
lnxt[le]=lfir[la];
lfir[la]=le++;
}
void insert(int a,int b,int c)//插入边
{
u[e]=a;v[e]=b;w[e]=c;
nxt[e]=fir[a];
fir[a]=e++;
}
const int inf=2000000000;
int bfs()
{
int i,j,k,tm;
for(i=1;i<=n;i++)dis[i]=(i==1?0:inf);
memset(vis,0,sizeof(vis));
memset(lvis,0,sizeof(lvis));
while(!Q.empty())Q.pop();
Q.push(1);
while(!Q.empty())
{
int p=Q.top();Q.pop();
if(p==n)break;
if(vis[p])continue;
vis[p]=1;
for(k=fir[p];k!=-1;k=nxt[k])if(dis[ v[k] ]>dis[p]+w[k]){//更新边
dis[ v[k] ]=dis[p]+w[k];
Q.push(v[k]);
} if(lvis[lay[p]])continue;
lvis[lay[p]]=1; tm=lay[p]-1;
for(k=lfir[tm];k!=-1;k=lnxt[k])if(dis[ lu[k] ]>dis[p]+c){//更新上一层
dis[ lu[k] ]=dis[p]+c;
Q.push(lu[k]);
} tm=lay[p]+1;
for(k=lfir[tm];k!=-1;k=lnxt[k])if(dis[ lu[k] ]>dis[p]+c){//更新下一层
dis[ lu[k] ]=dis[p]+c;
Q.push(lu[k]);
}
}
if(dis[n]==inf)return -1;
return dis[n];
}
int main()
{
int t,i,j,k,cas=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&c);
le=0;
memset(lfir,-1,sizeof(lfir));
for(i=1;i<=n;i++){
scanf("%d",&lay[i]);
linsert(lay[i],i);
}
int a,b,c;
e=0;
memset(fir,-1,sizeof(fir));
for(i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
insert(a,b,c);
insert(b,a,c);
}
int ans=bfs();
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}
上一篇:PHP之缩略图


下一篇:php文本操作方法集合比较第2页