zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", ans);
    	return 0;
    }
    

      

    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    [转载]企业级服务器设计与实现经验之系统框架(一)
    【转载】es通信框架
    【转载】企业级服务器设计与实现经验之插件系统基础篇
    阻塞队列
    [转载]ESFramework 4.0 进阶(01)-- 消息
    心跳监测器 IHeartBeatChecker
    poj2470
    poj2478
    poj2418
    poj2481
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9446092.html
Copyright © 2011-2022 走看看