题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4725
题目意思:有n个层n个点,每个点只属于一个层,一个层可以有多个点(这点很坑)。点通往相邻的层上的点有代价c。有额外m条带权无向路,求点1到点n的最短路。
思路:主要是建图,建完图用spfa/dijkstra跑一边就是了。开始我用vector存每层的信息,相邻层的点相连,最后超时了。。。
所以不能单独用点与点相连。我们可以将层抽象成一个点,利用层的间接关系来达到点相连的目的。那么我们要连接的有:点 和 上一层抽象成的点,点和下一层抽象成的点,本层抽象成的点和该点即可。
为什么不连接该点与本层的关系呢?因为一层不只一个点,连接了会导致本层的点相互距离为0。
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<queue> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=2e5+10; struct node{ int v,w,next; }edge[maxn*4]; int head[maxn*4],visit[maxn],d[maxn]; int n,m,c,t,cnt; void init(){//初始化 memset(head,-1,sizeof(head)); memset(visit,0,sizeof(visit)); memset(d,0x3f,sizeof(d)); cnt=0; } void add(int u,int v,int w){//前向星连边 edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void spfa(){//spfa求最短路模板 queue<int >q; q.push(1); visit[1]=1; d[1]=0; while(!q.empty()){ int t=q.front(); q.pop(); visit[t]=0; for(int i=head[t];i!=-1;i=edge[i].next){ int v=edge[i].v; int w=edge[i].w; if(d[v]>d[t]+w){ d[v]=d[t]+w; if(!visit[v]){ visit[v]=1; q.push(v); } } } } } int main(){ scanf("%d",&t); int k=0; while(t--){ init(); int x,u,v,w; scanf("%d%d%d",&n,&m,&c); for(int i=1;i<=n;i++){ scanf("%d",&x); add(x+n,i,0);//连接本层与点 if(x>1) add(i,x+n-1,c);//点与上一层 if(x<n) add(i,x+n+1,c);//点与下一层 } for(int i=1;i<=m;i++){//额外点与点相连 scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } spfa(); if(d[n]>=inf||n<=0) printf("Case #%d: -1 ",++k); else printf("Case #%d: %d ",++k,d[n]); } return 0; }