hdu4725 拆点+最短路

时间:2023-12-31 14:43:50

题意:有 n 个点,每个点有它所在的层数,最多有 n 层,相邻两层之间的点可以互相到达,消耗 c (但同一层并不能直接到达),然后还有一些额外的路径,可以在两点间互相到达,并且消耗一定费用。问 1 点到 n 点的最小花费

将每一层拆成两个点,分别为进入层和出发层,然后相邻层的出发层可以指向进入层,花费 c,每个点可以到达其出发层,而进入层可以到达该点,花费 0 ,最后建立其余双向边,最短路

 #include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef pair<int,int> pii; struct cmp{
bool operator()(pii a,pii b){
return a.first>b.first;
}
}; int head[],point[],val[],nxt[],size;
int n,dist[]; void add(int a,int b,int v){
point[size]=b;
val[size]=v;
nxt[size]=head[a];
head[a]=size++;
} void dij(){
int i;
memset(dist,-,sizeof(dist));
dist[]=;
priority_queue<pii,vector<pii>,cmp>q;
q.push(make_pair(dist[],));
while(!q.empty()){
pii u=q.top();
q.pop();
if(u.first>dist[u.second])continue;
for(i=head[u.second];~i;i=nxt[i]){
int j=point[i],v=u.first+val[i];
if(dist[j]==-||dist[j]>v){
dist[j]=v;
q.push(make_pair(dist[j],j));
}
}
}
printf("%d\n",dist[n]);
} int main(){
int t;
while(scanf("%d",&t)!=EOF){
for(int q=;q<=t;q++){
printf("Case #%d: ",q);
memset(head,-,sizeof(head));
size=;
int m,c;
scanf("%d%d%d",&n,&m,&c);
int i,j;
for(i=;i<=n;i++){
int l;
scanf("%d",&l);
add(i,l+n,);
add(l+n+n,i,);
}
for(i=;i<n;i++){
add(i+n,i+n+n+,c);
add(i+n+,i+n+n,c);
}
for(i=;i<=m;i++){
int a,b,v;
scanf("%d%d%d",&a,&b,&v);
add(a,b,v);
add(b,a,v);
}
dij();
}
}
return ;
}