题目链接:http://www.nbuoj.com/v8.8/Problems/Problem.php?pid=2473
题意:中文题
题解:见代码,注意初始建边。
#include
using namespace std;
#define pb push_back
#define Pii pair // first dis ,second u
const int N = 2E5 + 7;
vectorG[N];
bool a[N], vis[N];
int n, m;
int dis[N];
void add(int u, int v, int w, bool sta) //规定到达u点时,接下来u要减速为不正常点,否则正常
{
if(sta) {
G[u].pb(Pii(2 * w, n + v)); //u->v 建立一条2c的边, 并且到达v点时不正常
G[u + n].pb(Pii(2 * w, n + v)); //也可以由不正常u到达
} else {
G[u].pb(Pii(w, v)); //常规建边
G[u + n].pb(Pii(2 * w, v)); //不正常u点经过了一次减速,在减速一次到达正常v点
}
}
void dij()
{
priority_queue, greater > que;
que.push(Pii(0,0));
while(!que.empty()) {
int u = que.top().second;
que.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = 0;i < G[u].size();i ++) {
Pii t = G[u][i];
if(!vis[t.second] && dis[t.second] > t.first + dis[u]) {
dis[t.second] = t.first + dis[u];
que.push(Pii(dis[t.second], t.second));
}
}
}
}
int main()
{
scanf("%d %d", &n, &m);
memset(dis, 0x3f, sizeof(dis));
dis[0] = 0;
dis[n] = 0;
for(int i = 0;i < n;i ++) scanf("%d", &a[i]);
for(int i = 1;i <= m;i ++) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
add(u, v, w, a[u]);
add(v, u, w, a[v]);
}
dij();
printf("%d\n", min(dis[n-1], dis[2*n-1]));
return 0;
}