• [洛谷P5340][TJOI2019]大中锋的游乐场


    题目大意:有$n(nleqslant10^4)$个点,$m(mleqslant10^5)$条边的无向图,每个点有一个属性$A/B$,要求$|cnt_A-cnt_B|leqslant k(kleqslant10)$,问$S o T$最短路径

    题解:把每个点拆成$2k+1$个点,分别标号为$[-k,k]$,表示到这$cnt_A-cnt_B$的值,跑最短路即可。

    卡点:各种地方没有把$n$改成$n(2k+1)$

    C++ Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #define maxn (10010 * 21)
    #define maxm (100010 * 21)
    
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt, w;
    } e[maxm << 1];
    inline void addedge(int a, int b, int c) {
    	e[++cnt] = (Edge) { b, head[a], c }; head[a] = cnt;
    }
    
    int n, m, k, K, S, T;
    
    namespace Graph {
    	int V[maxn << 2];
    	long long dis[maxn];
    	inline int getmin(int a, int b) { return dis[a] < dis[b] ? a : b; }
    
    	void modify(int rt, int l, int r, int p, int num) {
    		if (l == r) {
    			V[rt] = num;
    			return ;
    		}
    		const int mid = l + r >> 1;
    		if (p <= mid) modify(rt << 1, l, mid, p, num);
    		else modify(rt << 1 | 1, mid + 1, r, p, num);
    		V[rt] = getmin(V[rt << 1], V[rt << 1 | 1]);
    	}
    	long long dijkstra(int S, int T) {
    		const int N = n * K + 1;
    		memset(dis, 0x3f, sizeof dis);
    		memset(V, 0, sizeof V);
    		dis[S] = 0, modify(1, 1, N, S, S);
    		for (int TIM = n * K + 1; TIM; --TIM) {
    			int u = V[1];
    			modify(1, 1, N, u, 0);
    			for (int i = head[u]; i; i = e[i].nxt) {
    				int v = e[i].to;
    				if (dis[v] > dis[u] + e[i].w) {
    					dis[v] = dis[u] + e[i].w;
    					modify(1, 1, N, v, v);
    				}
    			}
    		}
    		return dis[T];
    	}
    }
    
    int TIM, w[maxn];
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	std::cin >> TIM;
    	while (TIM --> 0) {
    		std::cin >> n >> m >> k;
    		K = 2 * k + 1;
    		for (int i = 1, x; i <= n; ++i) std::cin >> x, w[i] = x - 1;
    		for (int i = 0, a, b, c; i < m; ++i) {
    			std::cin >> a >> b >> c;
    			--a, --b;
    			for (int j = 2; j <= K; ++j) {
    				if (w[b + 1]) addedge(a * K + j - 1, b * K + j, c);
    				else addedge(a * K + j, b * K + j - 1, c);
    				if (w[a + 1]) addedge(b * K + j - 1, a * K + j, c);
    				else addedge(b * K + j, a * K + j - 1, c);
    			}
    		}
    		std::cin >> S >> T;
    		--S, --T;
    		for (int j = 1; j <= K; ++j) addedge(T * K + j, n * K + 1, 0);
    		int St = S * K + k + 1;
    		if (w[S + 1]) ++St; else --St;
    		long long ans = Graph::dijkstra(St, n * K + 1);
    		std::cout << (ans == 0x3f3f3f3f3f3f3f3f ? -1 : ans) << '
    ';
    		if (TIM) {
    			memset(head, 0, sizeof head);
    			cnt = 0;
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    软件工程个人作业01
    阅读计划及浅读问题
    引言作业1
    多态和异常分析课后
    大道至简七八章阅读
    接口与继承 课后实践
    构建执法阅读笔记02
    冲刺第五天
    学习进度条七
    冲刺第四天
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/11097827.html
Copyright © 2020-2023  润新知