hdu 4725 最短路
思路:将每个layer拆成两个点,编号为N+x,和N+N+x。对所有属于layer x的点i,建N+x到i的有向边,在建i到N+N+x的有向边。最后对所有x号layer和x+1建一条N+N+x到N+x+1的有向边和一条N+N+x+1到N+x的有向边。
#include<set> #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<string> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define pb push_back #define mp make_pair #define Maxn 300010 #define Maxm 80002 #define LL __int64 #define Abs(x) ((x)>0?(x):(-x)) #define lson(x) (x<<1) #define rson(x) (x<<1|1) #define inf 1000000000 #define lowbit(x) (x&(-x)) #define clr(x,y) memset(x,y,sizeof(x)) #define Mod 1000000007 using namespace std; int head[Maxn],vi[Maxn],e,n,m,c; int dis[Maxn]; struct Edge{ int u,v,next; int val; }edge[Maxn*3]; struct Point{ int id; Point (int a){id=a;} int operator<(const Point &temp) const{ return dis[id]>dis[temp.id]; } }; priority_queue<Point> q; void init() { memset(head,-1,sizeof(head)); memset(vi,0,sizeof(vi)); e=0; } void add(int u,int v,int val) { edge[e].u=u,edge[e].v=v,edge[e].val=val,edge[e].next=head[u],head[u]=e++; } void spfa() { int i,j,v,now; for(i=0;i<Maxn;i++) dis[i]=inf; dis[1]=0; memset(vi,0,sizeof(vi)); Point p(0); while(!q.empty()) q.pop(); q.push(1); while(!q.empty()){ p=q.top(); now=p.id; q.pop(); if(now==n) return ; vi[now]=0; for(i=head[now];i!=-1;i=edge[i].next){ v=edge[i].v; if(dis[now]+edge[i].val<dis[v]){ dis[v]=dis[now]+edge[i].val; if(!vi[v]){ vi[v]=1; q.push(v); } } } } } int main() { int t,i,j,u,v,val,x,Case=0; scanf("%d",&t); while(t--){ init(); scanf("%d%d%d",&n,&m,&c); for(i=1;i<=n;i++){ scanf("%d",&x); add(n+x,i,0); add(i,2*n+x,0); vi[x]=1; } for(i=1;i<n;i++){ if(vi[i]&&vi[i+1]){ add(2*n+i,n+i+1,c); add(2*n+i+1,n+i,c); } } for(i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&val); add(u,v,val); add(v,u,val); } if(n==0){ printf("Case #%d: -1\n",++Case); continue; } spfa(); printf("Case #%d: ",++Case); if(dis[n]>=inf) printf("-1\n"); else printf("%d\n",dis[n]); } return 0; }