题意:有n个点 , m条无向边 , 每条边都是有权值 , 并且 , 每个点属于一个楼层 , 相同楼层之间可以通过 , 但是要花费 c , 求 1 到 n的最小花费。
解法:刚开始做得时候 , 我是直接把两个相邻楼层之间的点建立一条无向边 , 权值为c , 但是一直TEL , 一开始一直不明白是为什么 , 看了大牛的代码是通过把每个点拆成3个点来做 , 一开始也没明白 , 为什么我这么做会超时 , 我还一直在优化最短路算法 。 后来突然明白 , 我那种方法 , 主要时间不是花在找最短路上 , 而是在建图上面 , 因为 , 我们首先要找到当前点和哪些点的楼层是相邻的 , 这就需要遍历所有点 , 由于有10^5个点 ,那就肯定要超时了 。 而大神那种做法 , 对于建图只需要O(1)的常数时间 , 这就是我TEL的原因。
建图:对于每个点 , 拆成3个点:1、本身 , 2、看做是层下的点,只跟当前点的上一层相连 , 2、看做是层上点 , 只跟当前点的下一层相连 , 并且都是单向边。
代码:
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 300100
#define INF 2000000000
#define min(x ,y) (x)<(y)?(x):(y)
struct node
{
int u;
int d;
}e;
int pre[maxn] ;
int dist[maxn];
vectorgrap[maxn];
int n , m , c;
int xy;
void init()
{
for(int i = 1; i <= 3*n; i++)
grap[i].clear();
}
struct node1
{
int u;
int d;
bool operator < (const node1 &rhs)const
{
return d > rhs.d;
}
}f;
void addedge(int x , int y , int z)
{
e.u = y , e.d = z;
grap[x].push_back(e);
}
void dijkstra()
{
priority_queueq;
f.u = 1 , f.d
= 0;
q.push(f);
int i ;
for(i = 1; i <= 3*n; i++)
dist[i] = INF;
dist[1] = 0;
memset(pre , 0 , sizeof(pre));
while(!q.empty())
{
f = q.top(); q.pop();
int u = f.u;//cout<<u<<endl;
if(u == n)
return ;
if(pre[u])
continue;
pre[u] = 1;
for(i = 0; i < grap[u].size(); i++)
{
e = grap[u][i];
if(dist[e.u] > dist[u]+e.d)
{
dist[e.u] = dist[u]+e.d;
f.u = e.u;
f.d = dist[e.u];
q.push(f);
}
}
}
}
int main()
{
//
cout<<INF<<endl;
int t , tcase = 1;
cin>>t;
while(t--)
{
scanf("%d %d %d" , &n , &m , &c);
init();
int i , x , y ;
int z;
for(i = 1;i <= n;i++)
{
scanf("%d",&xy);
addedge(i,n + 2*xy - 1,0);
addedge(n + 2*xy ,i,0);
}
for( i = 1;i < n;i++)
{
addedge(n + 2*i-1,n + 2*(i+1),c);
addedge(n + 2*(i+1)-1,n + 2*i,c);
}
while(m--)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
dijkstra();
if(dist[n] == INF)
{
printf("Case #%d: %d\n" , tcase++ , -1);
}
else
{
printf("Case #%d: %d\n" , tcase++ , dist[n]);
//cout<<dist[n]<<endl;
}
}
return 0;
}
解法:刚开始做得时候 , 我是直接把两个相邻楼层之间的点建立一条无向边 , 权值为c , 但是一直TEL , 一开始一直不明白是为什么 , 看了大牛的代码是通过把每个点拆成3个点来做 , 一开始也没明白 , 为什么我这么做会超时 , 我还一直在优化最短路算法 。 后来突然明白 , 我那种方法 , 主要时间不是花在找最短路上 , 而是在建图上面 , 因为 , 我们首先要找到当前点和哪些点的楼层是相邻的 , 这就需要遍历所有点 , 由于有10^5个点 ,那就肯定要超时了 。 而大神那种做法 , 对于建图只需要O(1)的常数时间 , 这就是我TEL的原因。
建图:对于每个点 , 拆成3个点:1、本身 , 2、看做是层下的点,只跟当前点的上一层相连 , 2、看做是层上点 , 只跟当前点的下一层相连 , 并且都是单向边。
代码:
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 300100
#define INF
#define min(x ,y) (x)<(y)?(x):(y)
struct node
{
}e;
int pre[maxn] ;
int
vectorgrap[maxn];
int n , m , c;
int xy;
void init()
{
}
struct node1
{
}f;
void addedge(int x , int y , int z)
{
}
void dijkstra()
{
}
int main()
{
//
}