JZOJ 3470
Description
给定一个n个点m条边的有向图,有k个标记点,要求从规定的起点按任意顺序经过所有标记点到达规定的终点,问最短的距离是多少。
Input
第一行5个整数n、m、k、s、t,表示点个数、边条数、标记点个数、起点编号、终点编号。
接下来m行每行3个整数x、y、z,表示有一条从x到y的长为z的有向边。
接下来k行每行一个整数表示标记点编号。
Output
输出一个整数,表示最短距离,若没有方案可行输出-1。
Sample Input
3 3 2 1 1
1 2 1
2 3 1
3 1 1
2
3
Sample Output
3
【样例解释】
路径为1->2->3->1。
Data Constraint
20%的数据n<=10。
50%的数据n<=1000。
另有20%的数据k=0。
100%的数据n<=50000,m<=100000,0<=k<=10,1<=z<=5000。
从起点,必经点作最短路
之后用这些 dst 数组跑 dp
f[i][j] 表示经过必经点的集合为 i ,最后一个点为 j 时,最短的经过路程
更新一个状态之后 dfs 一路更新下去,直到不能更新为止,否则会漏状态(不 dfs 也能 A,不过经打印测试,会有状态没被更新)
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
#include<bitset>
#include<queue>
#define INF 2000000000000000ll
using namespace std;
typedef long long ll;
const int MAXN = 50005, MAXM = 100005;
struct EDGE{
int nxt, to;
ll val;
EDGE(int NXT = 0, int TO = 0, ll VAL = 0ll) {nxt = NXT; to = TO; val = VAL;}
}edge[MAXM];
int n, m, k, s, t, totedge, maxs;
int head[MAXN], dest[15];
ll dst[15][MAXN], f[1 << 10][15];
bitset<MAXN> vis;
inline int rd() {
register int x = 0;
register char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) {
x = x * 10 + (c ^ 48);
c = getchar();
}
return x;
}
inline void add(int x, int y, ll v) {
edge[++totedge] = EDGE(head[x], y, v);
head[x] = totedge;
return;
}
inline void dij(int bgn, ll d[MAXN]) {
vis.reset();
for(int i = 1; i <= n; ++i) d[i] = INF;
priority_queue<pair<ll, int> > q;
d[bgn] = 0ll;
q.push(make_pair(0ll, bgn));
while(!q.empty()) {
int x = q.top().second; q.pop();
if(vis.test(x)) continue;
vis.set(x);
for(int i = head[x]; i; i = edge[i].nxt) {
int y = edge[i].to;
if(d[x] + edge[i].val < d[y]) {
d[y] = d[x] + edge[i].val;
q.push(make_pair(-d[y], y));
}
}
}
return;
}
void dfs(int s, int cur) {
if(s == maxs - 1) return;
for(int i = 1; i <= k; ++i) if(i != cur && (s & (1 << (i - 1))) == 0) {
if(f[s | (1 << (i - 1))][i] > f[s][cur] + dst[cur][dest[i]]) {
f[s | (1 << (i - 1))][i] = f[s][cur] + dst[cur][dest[i]];
dfs((s | (1 << (i - 1))), i);
}
}
return;
}
int main() {
n = rd(); m = rd(); k = rd(); s = rd(); t = rd();
register int xx, yy, vv;
for(int i = 1; i <= m; ++i) {
xx = rd(); yy = rd(); vv = (ll)rd();
if(xx != yy) add(xx, yy, vv);
}
dij(s, dst[k + 1]);
if(!k) {
if(dst[k + 1][t] == INF) puts("-1");
else printf("%lld\n", dst[k + 1][t]);
return 0;
}
for(int i = 1; i <= k; ++i) {
dest[i] = rd();
dij(dest[i], dst[i]);
}
maxs = (1 << k);
for(int i = 1; i <= k; ++i) for(int j = 0; j < maxs; ++j) f[j][i] = INF;
for(int i = 1; i <= k; ++i) f[1 << (i - 1)][i] = dst[k + 1][dest[i]];
for(int s = 0; s < maxs; ++s) {
for(int i = 1; i <= k; ++i) if(f[s][i] != INF) dfs(s, i);
}
ll ans = INF;
for(int i = 1; i <= k; ++i) {
f[maxs - 1][i] += dst[i][t];
ans = min(ans, f[maxs - 1][i]);
}
if(ans == INF) puts("-1");
else printf("%lld\n", ans);
return 0;
}
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/

浙公网安备 33010602011771号