题目:
自己没做出,看了大神的代码,学到了有用的东西。
若果将所有相邻两层的点都加一条边,肯定会爆的,此题考验的是构图能力,可以在每一层添加两个虚拟节点,第i层的两个额外节点为:Ai和Bi
可以构建下面这样的图:
是不是直观看都简单多了。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int,int>PII;
const int maxn=300010;
const int maxe=maxn*2;
int N,M,C,ecnt;
int head[maxn];
struct Edge{
int to,w,next;
}e[maxe];
void init()
{
ecnt=1;
memset(head,0,3*(N+1)*sizeof(int));
}
inline void add_edge(int u,int v,int w)
{
e[ecnt].to=v;
e[ecnt].w=w;
e[ecnt].next=head[u];
head[u]=ecnt++;
}
int dis[maxn];
bool vis[maxn];
void Dijkstra(int st, int ed)
{
memset(dis, 0x7f, 3*(N+1)*sizeof(int));
memset(vis, 0, 3*(N+1)*sizeof(bool));
priority_queue<PII> que;
que.push(make_pair(0, st));
dis[st] = 0;
while(!que.empty())
{
int u = que.top().second;
que.pop();
if(vis[u]) continue;
if(u == ed) return ;
vis[u] = true;
for(int p = head[u]; p; p = e[p].next)
{
int &v = e[p].to;
if(dis[v] > dis[u] + e[p].w)
{
dis[v] = dis[u] + e[p].w;
que.push(make_pair(-dis[v], v));
}
}
}
}
inline int readint()
{
char c = getchar();
while(!isdigit(c)) c = getchar();
int ret = 0;
while(isdigit(c)) ret = ret * 10 + c - '0', c = getchar();
return ret;
}
int main()
{
int T,cas=1;
T=readint();
while(T--)
{
N=readint(),M=readint(),C=readint();
init();
int lay;
for(int i=1;i<=N;i++)
{
lay=readint();
add_edge(i,N+2*lay,0);
add_edge(N+2*lay-1,i,0);
}
for(int i=1;i<N;i++)
{
add_edge(N+i*2,N+(i+1)*2-1,C);
add_edge(N+2*(i+1),N+2*i-1,C);
}
int u,v,w;
for(int i=1;i<=M;i++)
{
u=readint(),v=readint(),w=readint();
add_edge(u,v,w);
add_edge(v,u,w);
}
Dijkstra(1,N);
if(dis[N]==0x7f7f7f7f) dis[N]=-1;
printf("Case #%d: %d\n",cas++,dis[N]);
}
return 0;
}