CF241E Flights

情到浓时终转凉″ 提交于 2019-12-02 03:24:37

首先这个题目问的是从\(1\)\(n\)的路径问题.所以我们可以先将与这些路径无关的边权直接赋为你喜欢的数\(\in\{1,2\}\).

\(dis[i]\)表示确定玩\(w[i]\)后从\(1\)\(i\)的最短距离.

那么对于剩下的任意一条边\(\{u,v\}\),必定有\(1\leq dis[v]-dis[u]\leq2\).

其实也很好理解,就是\(1\leq w[i]\leq2\)并且每一条路径长度要相同.

如果\(dis[v]-dis[u]>2\)\(dis[v]-dis[u]<1\),就一定出现了路径不同的边(\(w[i]\)无法弥补他们的差距).

于是我们就有了若干个约束.

于是将\(u\rightarrow v\)连一条\(1\)的边,将\(v\rightarrow u\)连一条\(-2\)的边.

跑差分约束即可.

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define il inline
#define rg register
#define gi read<int>
#define pii pair<int, int>
using namespace std;
const int N = 1010, M = 5010;
template<class TT>
il TT read() {
    TT o = 0,fl = 1; char ch = getchar();
    while (!isdigit(ch) && ch != '-') ch = getchar();
    if (ch == '-') fl = -1, ch = getchar();
    while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
    return fl * o;
}
queue<int>Q;
pii book[M];
int mp[N][N], n, m, dis[N], cnt[N];
bool vis[2][N], mark;
il void dfs(int u) {
    vis[mark][u] = 1;
    for (int v = 1; v <= n; ++v)
        if (mp[u][v] && !vis[mark][v])
            vis[mark][v] = 1, dfs(v);
}
il void spfa() {
    memset(dis, -63, sizeof dis);
    Q.push(1); cnt[1] = 1; dis[1] = 0;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        for (int v = 1; v <= n; ++v)
            if (mp[u][v] && dis[v] < dis[u] + mp[u][v]) {
                dis[v] = dis[u] + mp[u][v];
                Q.push(v); cnt[v]++;
                if (cnt[v] > n) exit(puts("No") & 0);
            }
    }
}
int main() {
    n = gi(), m = gi();
    for (int i = 1; i <= m; ++i) {
        int u = gi(), v = gi();
        book[i] = pii(u, v);
        mp[u][v] = 1;
    }
    mark = 0; dfs(1);
    for (int i = 1; i <= m; ++i) {
        mp[book[i].first][book[i].second] = 0;
        mp[book[i].second][book[i].first] = 1;
    }
    mark = 1; dfs(n);
    for (int i = 1; i <= m; ++i) {
        int u = book[i].first, v = book[i].second;
        mp[v][u] = 0;
        if (vis[0][u] && vis[1][u] && vis[0][v] && vis[1][v])
            mp[u][v] = 1, mp[v][u] = -2;
//      else printf("%d\n", i);
    }
    spfa(); puts("Yes");
    for (int i = 1; i <= m; ++i) {
        int u = book[i].first, v = book[i].second;
        if (mp[u][v]) printf("%d\n", dis[v] - dis[u]);
        else puts("2");
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!