zoukankan      html  css  js  c++  java
  • 【Codeforces Round #693 (Div. 3) G】Moving to the Capital

    题目链接

    链接

    翻译

    注意是有向图,不然这题读起来会觉得题目很奇怪。。

    题解

    bfs 求最短路 d[1..n],然后对于 (d_i<d_j) 的边连实线,否则连虚线。

    就可以做 dp 了,对于实线 dp[x] = min(dp[x],dp[y]),对于虚线 dp[x] = min(dp[x],d[y])

    虚线只能走一次嘛。然后实线还能顺着往下走。妥妥的记忆化,当然不要忘了待在原地不动的情况,对应 (dp[x]=min(dp[x],d[x]))

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    const int N = 2e5;
    const LL MOD = 1e9 + 7;
    const int K = 5000;
    
    int n, m, d[N+10],dp[N+10];
    vector<int> g[3][N + 10];
    queue<int> dl;
    
    void bfs() {
    	for (int i = 1; i <= n; i++) {
    		d[i] = n + 1;
    	}
    	d[1] = 0;
    	dl.push(1);
    	while (!dl.empty()) {
    		int x = dl.front();
    		dl.pop();
    		int len = g[0][x].size();
    		for (int y : g[0][x]) {
    			if (d[y] == n + 1) {
    				d[y] = d[x] + 1;
    				dl.push(y);
    			}
    		}
    	}
    }
    
    int dfs(int x) {
    	if (dp[x] != n + 1) {
    		return dp[x];
    	}
    	//实线可以任意走。
    	for (int y : g[1][x]) {
    		dp[x] = min(dp[x], dfs(y));
    	}
    	//虚线只能走一次。
    	for (int y : g[2][x]) {
    		dp[x] = min(dp[x], d[y]);
    	}
    	//待在原地
    	dp[x] = min(dp[x], d[x]);
    	return dp[x];
    }
    
    int main() {
    	#ifdef LOCAL_DEFINE
    		freopen("in.txt", "r", stdin);
    	#endif
    	ios::sync_with_stdio(0), cin.tie(0);
    	int T;
    	cin >> T;
    	while (T--) {
    		cin >> n >> m;
    		for (int i = 1; i <= n; i++) {
    			for (int j = 0; j < 3; j++) {
    				g[j][i].clear();
    			}
    		}
    		for (int i = 1; i <= m; i++) {
    			int x, y;
    			cin >> x >> y;
    			g[0][x].push_back(y);
    		}
    		bfs();
    		for (int x = 1; x <= n; x++) {
    			for (int y : g[0][x]) {
    				if (d[y] > d[x]) {
    					g[1][x].push_back(y);
    				}
    				else {
    					//虚线
    					g[2][x].push_back(y);
    				}
    			}
    		}
    		for (int i = 1; i <= n; i++) {
    			dp[i] = n + 1;
    		}
    		for (int i = 1; i <= n; i++) {
    			if (dp[i] == n + 1) {
    				dp[i] = dfs(i);
    			}
    		}
    		for (int i = 1; i <= n; i++) {
    			cout << dp[i] << " ";
    		}
    		cout << endl;
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    【设计模式】6.模板方法模式
    【设计模式】5.原型模式
    【设计模式】4.工厂模式
    【设计模式】3.代理模式
    zookeeper集群的搭建
    zookeeper实现分布式锁的原理和一个小例子
    zookeeper配置管理实现原理----监听事件watch
    zookeeper的javaAPI操作(基于Curator的CRUD)
    java.lang.IllegalArgumentException: A HostProvider may not be empty!
    Zookeeper的安装和基本操作
  • 原文地址:https://www.cnblogs.com/AWCXV/p/14264321.html
Copyright © 2011-2022 走看看