题意:有 n 个点,每个点有它所在的层数,最多有 n 层,相邻两层之间的点可以互相到达,消耗 c (但同一层并不能直接到达),然后还有一些额外的路径,可以在两点间互相到达,并且消耗一定费用。问 1 点到 n 点的最小花费
将每一层拆成两个点,分别为进入层和出发层,然后相邻层的出发层可以指向进入层,花费 c,每个点可以到达其出发层,而进入层可以到达该点,花费 0 ,最后建立其余双向边,最短路
1 #include<stdio.h> 2 #include<string.h> 3 #include<vector> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 typedef pair<int,int> pii; 8 9 struct cmp{ 10 bool operator()(pii a,pii b){ 11 return a.first>b.first; 12 } 13 }; 14 15 int head[300005],point[1000005],val[1000005],nxt[1000005],size; 16 int n,dist[300005]; 17 18 void add(int a,int b,int v){ 19 point[size]=b; 20 val[size]=v; 21 nxt[size]=head[a]; 22 head[a]=size++; 23 } 24 25 void dij(){ 26 int i; 27 memset(dist,-1,sizeof(dist)); 28 dist[1]=0; 29 priority_queue<pii,vector<pii>,cmp>q; 30 q.push(make_pair(dist[1],1)); 31 while(!q.empty()){ 32 pii u=q.top(); 33 q.pop(); 34 if(u.first>dist[u.second])continue; 35 for(i=head[u.second];~i;i=nxt[i]){ 36 int j=point[i],v=u.first+val[i]; 37 if(dist[j]==-1||dist[j]>v){ 38 dist[j]=v; 39 q.push(make_pair(dist[j],j)); 40 } 41 } 42 } 43 printf("%d\n",dist[n]); 44 } 45 46 int main(){ 47 int t; 48 while(scanf("%d",&t)!=EOF){ 49 for(int q=1;q<=t;q++){ 50 printf("Case #%d: ",q); 51 memset(head,-1,sizeof(head)); 52 size=0; 53 int m,c; 54 scanf("%d%d%d",&n,&m,&c); 55 int i,j; 56 for(i=1;i<=n;i++){ 57 int l; 58 scanf("%d",&l); 59 add(i,l+n,0); 60 add(l+n+n,i,0); 61 } 62 for(i=1;i<n;i++){ 63 add(i+n,i+n+n+1,c); 64 add(i+n+1,i+n+n,c); 65 } 66 for(i=1;i<=m;i++){ 67 int a,b,v; 68 scanf("%d%d%d",&a,&b,&v); 69 add(a,b,v); 70 add(b,a,v); 71 } 72 dij(); 73 } 74 } 75 return 0; 76 }
时间: 2024-10-26 17:19:28