• [GXOI/GZOI2019]旅行者 (最短路)


    题意

    给定一个有向图,其中一些顶点为关键点。求这些关键点两两之间最小距离。

    题解

    考试时没怎么想写了50分暴力走了。以为是什么强连通分量的解法,结果就是个最短路。直接从关键点跑一次最短路dis[0],再把图反向在跑一次最短路dis[1]。跑最短路的时候记录起点col[0/1]。那么最后直接枚举一条边(x,y,w),当col[0][x]!=col[1][y]时,答案一定在所有dis[0][x]+w+dis[1][y]中,取最小值即可。

    相当于把路径拆成3部分。

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    inline void read(int &x) {
    	char ch; while(!isdigit(ch=getchar()));
    	for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');
    }
    typedef long long LL;
    const int MAXN = 100005;
    const int MAXM = 500005;
    const LL inf = 1ll<<50;
    int n, m, k, a[MAXN], fir[MAXN], to[MAXM], nxt[MAXM], wt[MAXM], cnt;
    inline void link(int u, int v, int w) { if(u == v) return;
    	to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; wt[cnt] = w;
    }
    bool inq[MAXN];
    queue<int>q;
    void spfa(LL* dis, int* col) {
    	for(int i = 1; i <= n; ++i) dis[i] = inf, col[i] = 0;
    	for(int i = 1; i <= k; ++i) dis[a[i]] = 0, col[a[i]] = a[i], q.push(a[i]), inq[a[i]] = 1;
    	while(!q.empty()) {
    		int u = q.front(); q.pop(); inq[u] = 0;
    		for(int v, i = fir[u]; i; i = nxt[i])
    			if(dis[v=to[i]] > dis[u] + wt[i]) {
    				dis[v] = dis[u] + wt[i];
    				col[v] = col[u];
    				if(!inq[v]) inq[v] = 1, q.push(v);
    			}
    	}
    }
    LL dis[2][MAXN];
    int col[2][MAXN];
    int U[MAXM], V[MAXM], W[MAXM];
    int main () {
    	int T;
    	read(T);
    	while(T--) {
    		read(n), read(m), read(k);
    		for(int i = 1; i <= n; ++i) fir[i] = 0; cnt = 0;
    		for(int i = 1; i <= m; ++i)
    			read(U[i]), read(V[i]), read(W[i]), link(U[i], V[i], W[i]);
    		for(int i = 1; i <= k; ++i) read(a[i]);
    		spfa(dis[0], col[0]);
    		for(int i = 1; i <= n; ++i) fir[i] = 0; cnt = 0;
    		for(int i = 1; i <= m; ++i)
    			link(V[i], U[i], W[i]);
    		spfa(dis[1], col[1]);
    		LL ans = inf;
    		for(int i = 1; i <= m; ++i) {
    			int x = U[i], y = V[i];
    			if(col[0][x] && col[1][y] && col[0][x]!=col[1][y])
    				ans = min(ans, dis[0][x] + dis[1][y] + W[i]);
    		}
    		printf("%lld
    ", ans);
    	}
    }
    
  • 相关阅读:
    $NOIP2018$赛道修建
    $NOIP2005$过河
    $NOIP2014$飞扬的小鸟
    $[SCOI2014]$方伯伯的玉米田
    大吉大利,晚上吃鸡!
    $HNOI2005$星际贸易
    $CF1142B$ $Lynyrd Skynyrd$
    $SDOI2015$排序
    $NOIP2003$侦探推理
    Build 2016概览
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12051382.html
Copyright © 2020-2023  润新知