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\n", 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;
}
posted @ 2020-09-13 21:40  这知识他不进我的脑子  阅读(213)  评论(0编辑  收藏  举报