题意:有N个点和N层..一层有X个点(0<=X<=N).两邻两层间有一条路花费C。还有M条小路在两个点之间。问从第一个点走到第N个点最短路是多少...
可以考虑在每一层增加一个点,这个点到上下层的距离是C,与本层的距离是0;
////////////////////////////////////////////////////
时间卡的很恶心,还需要双端队列,如果新加入的点的值比队列顶端的额值小就放在方面,否则就放在下面(不明白优化在那里了.......)
#include<stdio.h>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn = 1000005;
const int maxm = 100005;
const int oo = 0xfffffff;
struct node
{
int u, v, c, next;
}e[maxn];
int head[maxm*3], dis[maxm*3];
bool use[maxm*3];
void Add(int u, int v, int w, int k)
{
e[k].u = u;
e[k].v = v;
e[k].c = w;
e[k].next = head[u];
head[u] = k;
}
void spfa()
{
deque<int> Q;
Q.push_back(1);
while(Q.size())
{
int i = Q.front();Q.pop_front();
use[i] = false;
for(int j=head[i]; j!=0; j=e[j].next)
{
int u=e[j].u, v=e[j].v, w=e[j].c;
if(dis[u]+w < dis[v])
{
dis[v] = dis[u] + w;
if(use[v] == false)
{
use[v] = true;
if(Q.size() && dis[v] < dis[Q.front()])
Q.push_front(v);
else
Q.push_back(v);
}
}
}
}
}
int main()
{
int T, t=1;
scanf("%d", &T);
while(T--)
{
int i, N, M, C, u, v, w, x, k=1;
scanf("%d%d%d", &N, &M, &C);
memset(head, 0, sizeof(head));
for(i=1; i<=N; i++)
{
//本层拆出来的点是 出i+N, 入i+2*N
dis[i] = dis[i+N] = dis[i+2*N] = oo;
if(i != N)
{
Add(i+N, i+2*N+1, C, k++);
Add(i+N+1, i+2*N, C, k++);
}
scanf("%d", &x);//节点i属于第x层
Add(i, x+N, 0, k++);
Add(x+2*N, i, 0, k++);
}
for(i=1; i<=M; i++)
{
scanf("%d%d%d", &u, &v, &w);
Add(u, v, w, k++);
Add(v, u, w, k++);
}
dis[1] = 0;
spfa();
if(dis[N] == oo)
printf("Case #%d: -1 ", t++);
else
printf("Case #%d: %d ", t++, dis[N]);
}
return 0;
}
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn = 1000005;
const int maxm = 100005;
const int oo = 0xfffffff;
struct node
{
int u, v, c, next;
}e[maxn];
int head[maxm*3], dis[maxm*3];
bool use[maxm*3];
void Add(int u, int v, int w, int k)
{
e[k].u = u;
e[k].v = v;
e[k].c = w;
e[k].next = head[u];
head[u] = k;
}
void spfa()
{
deque<int> Q;
Q.push_back(1);
while(Q.size())
{
int i = Q.front();Q.pop_front();
use[i] = false;
for(int j=head[i]; j!=0; j=e[j].next)
{
int u=e[j].u, v=e[j].v, w=e[j].c;
if(dis[u]+w < dis[v])
{
dis[v] = dis[u] + w;
if(use[v] == false)
{
use[v] = true;
if(Q.size() && dis[v] < dis[Q.front()])
Q.push_front(v);
else
Q.push_back(v);
}
}
}
}
}
int main()
{
int T, t=1;
scanf("%d", &T);
while(T--)
{
int i, N, M, C, u, v, w, x, k=1;
scanf("%d%d%d", &N, &M, &C);
memset(head, 0, sizeof(head));
for(i=1; i<=N; i++)
{
//本层拆出来的点是 出i+N, 入i+2*N
dis[i] = dis[i+N] = dis[i+2*N] = oo;
if(i != N)
{
Add(i+N, i+2*N+1, C, k++);
Add(i+N+1, i+2*N, C, k++);
}
scanf("%d", &x);//节点i属于第x层
Add(i, x+N, 0, k++);
Add(x+2*N, i, 0, k++);
}
for(i=1; i<=M; i++)
{
scanf("%d%d%d", &u, &v, &w);
Add(u, v, w, k++);
Add(v, u, w, k++);
}
dis[1] = 0;
spfa();
if(dis[N] == oo)
printf("Case #%d: -1 ", t++);
else
printf("Case #%d: %d ", t++, dis[N]);
}
return 0;
}