zoukankan      html  css  js  c++  java
  • CF1407E-Egor in the Republic of Dagestan【思维+最短路】

    @洛谷的链接
    题目描述
    给定一张(n)个点,(m)条边的有向图,每条为白色或者黑色,只有出发点和边为相同颜色时才能通行。求一种对点的标色方案,使得最短路的最大,也可以选择被困在这张图中出不去(-1)。
    思路
    考虑反向建边,这样就可以使得边的颜色和点的颜色一致。如果能够有一种方案被困在图中,那么就尽可能的困在图中。所以对于一个点有以下情况:
    (w[x]):该点为白色时到该点的最短距离,(w[x] = min(w[x], f[x] + 1))
    (b[x]):该点为黑色时到点的最短距离,(b[x] = min(b[x], f[x]+1))
    (f[x]):到该点时,(w[x])(b[x])更大的值,当且仅当(w[x])(b[x])都存在时才更新。(如果有一种方式达不到,就说明可以留在图中)。
    最后的答案也是对(f[1])的判断。染色就很容易,对于一个点,如果(w[x]>b[x]),就染白色,否则染成黑色。
    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const int N = 5e5 + 10;
    
    vector<int> be[N], we[N];
    int f[N], w[N], b[N];
    bool inq[N];
    
    void solve() {
        int n, m;
        cin >> n >> m;
        for(int i = 1; i <= m; i++) {
            int v, u, op;
            scanf("%d%d%d", &v, &u, &op);
            if(op == 1) {
                we[u].push_back(v);
            } else {
                be[u].push_back(v);
            }
        }
    
        memset(f, 0x3f, sizeof f);
        memset(w, 0x3f, sizeof f);
        memset(b, 0x3f, sizeof f);
        queue<int> q;
        q.push(n);
        f[n] = w[n] = b[n] = 0;
        while(!q.empty()) {
            int u = q.front(); q.pop();
            inq[u] = false;
            for(int i = 0; i < we[u].size(); i++) {
                int v = we[u][i];
                if(w[v] > f[u] + 1) {
                    w[v] = f[u] + 1;
                    if(max(w[v], b[v]) < inf) {
                        f[v] = max(w[v], b[v]);
                        if(!inq[v]) {
                            inq[v] = true;
                            q.push(v);
                        }
                    }
                }
            }
            for(int i = 0; i < be[u].size(); i++) {
                int v = be[u][i];
                if(b[v] > f[u] + 1) {
                    b[v] = f[u] + 1;
                    if(max(b[v], w[v]) < inf) {
                        f[v] = max(w[v], b[v]);
                        if(!inq[v]) {
                            inq[v] = true;
                            q.push(v);
                        }
                    }
                }
            }
        }
    
        if(f[1] == inf) puts("-1");
        else printf("%d
    ", f[1]);
    
        for(int i = 1; i <= n; i++) {
            if(w[i] > b[i]) printf("1");
            else printf("0");
        }
    }
    
    int main() {
        // freopen("in.txt", "r", stdin);
        solve();
        return 0;
    }
    
  • 相关阅读:
    css选择器中:first-child与:first-of-type的区别
    Chrome 快捷键
    notepad++ html格式化
    Linux VFS的主要的数据结构
    Linux根文件系统介绍
    Linux文件系统测试工具
    p​o​s​t​m​a​r​k​使​用
    虚拟文件系统
    linux文件系统初始化过程(6)---执行init程序
    linux文件系统初始化过程(4)---加载initrd(中)
  • 原文地址:https://www.cnblogs.com/ZX-GO/p/13663502.html
Copyright © 2011-2022 走看看