与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]));
}
}
}
}