题目描述
给出一幅由 n 个点 m 条边构成的无向带权图。其中有些点是黑点,另外点是白点。
现在每个白点都要与他距离最近的黑点通过最短路连接(如果有很多个,可以选取其中任意一个),我们想要使得选出的边花费的代价最小。请问这个最小代价是多少?
注意:最后选出的边须保证每个白点到黑点的距离仍然是最短距离。
输入
第一行两个整数n,m
第二行n个整数,0表示白点,1表示黑点
接下来m行,每行三个整数x,y,z,表示一条连接x和y点,权值为z的边。
输出
如果无解,输出impossible;否则,输出最小代价
样例输入
复制样例数据
5 7 0 1 0 1 0 1 2 11 1 3 1 1 5 17 2 3 1 3 5 18 4 5 3 2 4 5
样例输出
5
提示
对于30%的数据,1≤n≤10,1≤m≤20。
对于100%的数据,1≤n≤105,1≤m≤2×105,1≤z≤109。
题解:因为要满足白色到黑色的最短距离,我们倒过来想,所以我们建立一个源点,源点到每个黑色的距离为0,跑一边最短路,把是最短路的边加起来即可,注意(dis[to] == dis[now.id] + e[i].d && e[i].d < pre[to]),即为更新这个节点的路径选择最短的,既满足最小花费。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
struct edge {
int to, nex, d;
}e[N * 4];
using namespace std;
int n, m;
int head[N], len, vis[N], pre[N];
int book[N];
ll dis[N];
ll ans;
void init() {
for(int i = 0; i <= n + 1; i++) {
head[i] = -1;
dis[i] = 1e18;
pre[i] = 0;
}
}
void Add_edge(int x, int y, int z) {
e[len].to = y;
e[len].d = z;
e[len].nex = head[x];
head[x] = len++;
}
struct node {
int id;
ll d;
node() {}
node(int id_, ll d_) {
id = id_;
d = d_;
}
bool operator <(const node &b)const {
return d > b.d;
}
};
void DIJ() {
priority_queue<node> q;
node now;
int to;
q.push(node(0, 0));
dis[0] = 0;
while(!q.empty()) {
now = q.top(); q.pop();
if(vis[now.id]) continue;
vis[now.id] = 1;
// cout<<now.id<<" : "<<endl;
for(int i = head[now.id]; i != -1; i = e[i].nex) {
to = e[i].to;
// cout<<to<<endl;
if(dis[to] > dis[now.id] + e[i].d || (dis[to] == dis[now.id] + e[i].d && e[i].d < pre[to])) {
dis[to] = dis[now.id] + e[i].d;
ans = ans - pre[to] + e[i].d;
pre[to] = e[i].d;
q.push(node(to, dis[to]));
}
}
}
int flag = 0;
for(int i = 1; i <= n; i++)
if(book[i] == 0 && dis[i] == 1e18)
flag = 1;
if(flag) printf("impossible\n");
else printf("%lld\n", ans);
}
int main() {
int x, y, z;
scanf("%d %d", &n, &m);
init();
for(int i = 1; i <= n; i++) {
scanf("%d", &book[i]);
if(book[i] == 1) {
Add_edge(0, i, 0);
Add_edge(i, 0, 0);
}
}
for(int i = 1; i <= m; i++) {
scanf("%d %d %d", &x, &y, &z);
Add_edge(x, y, z);
Add_edge(y, x, z);
}
DIJ();
return 0;
}