ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Moving to the Capital

2021-01-07 14:03:44  阅读:237  来源: 互联网

标签:题目 int 城市 MAXN Capital Moving include size


Moving to the Capital

题目来源:Codeforces Round #693 G

题目链接:https://codeforces.com/contest/1472/problem/G

题目大意

\(n\) 个城市,\(m\) 条单向路径,长度都为 \(1\) 。\(d_i\)表示从首都 \(1\) 到城市i的最短距离。然后就是说从城市 \(i\) 到 \(j\) 有两种行为,第一种随便用,第二种最多只能用一次。我们要求的是从每个城市出发,最终能距首都的最短距离。

解题思路

用\(f\)表示最终结果,\(f[i]\) 的初值等于 \(d[i]\)。我们按 \(d\) 从大到小枚举城市 \(u\),\(u\) 可以到达城市 \(v\)。

那么如果 \(d[u] < d[v]\),则 \(u\) 可以直接采用行为 \(1\) 到达 \(v\),因为是按 \(d\) 从大到小枚举,所以此时 \(f[v]\) 是已知的,则可得 \(f[u] = min(f[u], f[v])\)。

如果 \(d[u] >= d[v]\),那么 \(u\) 只能采取行为 \(2\) 到 \(v\),因为已经用过行为 \(2\),所以 \(v\) 之后只能用 \(1\) 了,即只能往 \(d\) 增大的城市走,所以 \(d[v]\) 是最小值,可得 \(f[u] = min(f[u], d[v])\)。

Code

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXN 200005


int d[MAXN], f[MAXN];
bool vis[MAXN];
vector<int> edges[MAXN], c[MAXN];

int main(void)
{
    int T; scanf("%d", &T);
    while(T--) {
        int n, m; scanf("%d%d", &n, &m);
        for(int i=0;i<=n;++i) edges[i].clear(), c[i].clear();
        for(int i=0;i<m;++i) {
            int u, v; scanf("%d%d", &u, &v);
            edges[u].push_back(v);
        }
        // 求d
        memset(vis, false, (n+1) * sizeof(bool));
        queue<int> Q;
        d[1] = 0; vis[1] = true;
        Q.push(1);
        while(Q.size()) {
            int u = Q.front(); Q.pop();
            c[d[u]].push_back(u);           // 与1距离相同的点放一起
            int len = edges[u].size();
            for(int i=0;i<len;++i) {
                int v = edges[u][i];
                if(vis[v]) continue;
                d[v] = d[u] + 1;
                vis[v] = true;
                Q.push(v);
            }
        }
        // 求结果f
        for(int i=1;i<=n;++i) f[i] = d[i];  // f初值等于d
        for(int l=n-1;l>0;--l) {            // 由远到近遍历每一点
            int num = c[l].size();
            for(int i=0;i<num;++i) {
                int u = c[l][i];
                int len = edges[u].size();
                for(int j=0;j<len;++j) {
                    int v = edges[u][j];
                    if(d[u] < d[v]) f[u] = min(f[u], f[v]);
                    else f[u] = min(f[u], d[v]);
                }
            }
        }
        for(int i=1;i<=n;++i) printf("%d ", f[i]);
        printf("\n");
    }
    return 0;
}

标签:题目,int,城市,MAXN,Capital,Moving,include,size
来源: https://www.cnblogs.com/Fiona0726/p/14246093.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有