与hdu5521类似的层次网络最短路问题
http://acm.hdu.edu.cn/showproblem.php?pid=4725
题意是给 n个点,m个边,C
m条边u,v,w,w是边权
除此之外给你一个个 layer[i],表示点i属于第 layer[i]层!
关于层的性质有两个 【如果相邻两层都存在节点,则x层任意节点可以与x+1层任意节点互通,代价为C】
当然如果有一层为空,则空层是无法与上下层相通的哦!相当于断层!
建图方法和hdu5521一致,增一个点代表一层,不同的是,5521是【每一层的所有点互通】,而本题只要求相邻层互通,
注意:【层之内是不允许互通的】
因此建图需要注意 不能直接 【把新new的点 与层内的所有点直接建立双向边】
应该
A 【建立 该层内的节点 指向 当前层的新new的虚拟节点的单向边】【权值为0】
B、【第i层的虚拟节点指向 i+1层的所有node】【权值为C】
C、【第i+1层的虚拟节点指向 i层的所有node】【权值为C】
【这样就能确保符合题意,两层内任意节点互通,但同层节点不连通】
dji:561ms
#include <iostream> #include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #include<vector> #include<queue> using namespace std; struct node { int x; int v; node() {} node(int a,int b) { x=a,v=b; } bool operator <(const node&b) const { return v>b.v; } }; vector<node >mp[200005]; vector <int >layer[200005]; int idx; int vis[200005]; priority_queue<node> q; int dis[200005]; const int inf=1e9; int main() { int cnt=1; void dji(); int t; cin>>t; while(t--) { int n,m,c; int i,j; cin>>n>>m>>c; int x,y,v; for (i=1; i<=n*2; i++) mp[i].clear(); for (i=1;i<=n*2;i++) layer[i].clear(); for (i=1; i<=n; i++) { scanf("%d",&x); layer[x].push_back(i); } for (i=1; i<=m; i++) { scanf("%d%d%d",&x,&y,&v); mp[x].push_back(node(y,v)); mp[y].push_back(node(x,v)); } idx=n; for (i=1; i<=n; i++) { idx++; if (layer[i].size()==0) continue; for (j=0; j<layer[i].size(); j++) { v=layer[i][j]; //mp[idx].push_back(node(v,0));原先的错误建图法 mp[v].push_back(node(idx,0)); } } for (i=n+1; i<idx; i++) { if (layer[i-n].size()==0||layer[i-n+1].size()==0) continue; mp[i].push_back(node(i+1,c)); for (j=0; j<layer[i-n].size(); j++)//更正后的建图法 { v=layer[i-n][j]; mp[i+1].push_back(node(v,c)); //i+1-n层的虚拟节点指向i-n层的node } for (j=0; j<layer[i-n+1].size(); j++)//更正后的建图法 { v=layer[i-n+1][j]; mp[i].push_back(node(v,c));//i-n层的虚拟节点指向下一层的node } } dji(); printf("Case #%d: ",cnt++); if (dis[n]==inf) printf("-1\n"); else printf("%d\n",dis[n]); } return 0; } void dji() { while(!q.empty())q.pop(); int i; for (i=1;i<=idx;i++) { dis[i]=inf; vis[i]=0; } dis[1]=0; node st(1,0); q.push(st); while(!q.empty()) { node t=q.top(); q.pop(); int num=t.x; if (vis[num])continue; vis[num]=1; for (i=0;i<mp[num].size();i++) { node tmp=mp[num][i]; int x=tmp.x; int v=tmp.v; if (!vis[x]&&v+dis[num]<dis[x]) { dis[x]=v+dis[num]; q.push(node(x,dis[x])); } } } }