@ZCDHJ
2019-10-23T11:42:37.000000Z
字数 1747
阅读 570
差分约束
首先很显然对于任意在点 到点 路径上的点 ,所有从 到 的路径大小都是一样的。那么设 表示这个唯一的路径大小,对于每条合法边(两个端点都在 到 的路径上)有不等式:。
看出来了吗?差分约束就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
const int MAXN = 1000;
const int MAXM = 5000;
int n, m, edge;
int U[MAXM | 1], V[MAXM | 1], fst[MAXN | 1], dist[MAXN | 1], cnt[MAXN | 1], flag[MAXN | 1];
bool vis[MAXN | 1];
struct Edge {
int to, w, nxt;
Edge() : to(0), w(0), nxt(0) {}
Edge(int a, int b, int c) : to(b), w(c), nxt(fst[a]) {}
} e[MAXM << 1 | 1];
inline int read() {
register int x = 0;
register char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
inline void add_edge(int a, int b, int c) {
e[++edge] = Edge(a, b, c);
fst[a] = edge;
}
void dfs1(int x) {
if (vis[x]) return;
vis[x] = 1;
flag[x] = 1;
for (int k = fst[x]; k; k = e[k].nxt) {
int to = e[k].to;
if (e[k].w == 1) continue;
dfs1(to);
}
}
void dfs2(int x) {
if (vis[x]) return;
++flag[x];
vis[x] = 1;
for (int k = fst[x]; k; k = e[k].nxt) {
int to = e[k].to;
if (e[k].w == 0) continue;
dfs2(to);
}
}
void SPFA() {
std::queue < int > q;
q.push(1);
memset(dist, 0x3f, sizeof(dist));
dist[1] = 0;
do {
int from = q.front();
q.pop();
vis[from] = 0;
for (int k = fst[from]; k; k = e[k].nxt) {
int to = e[k].to, w = e[k].w;
if (dist[to] > dist[from] + w) {
dist[to] = dist[from] + w;
cnt[to] = cnt[from] + 1;
if (cnt[to] > n) {
puts("No");
exit(0);
}
if (!vis[to]) {
q.push(to);
vis[to] = 1;
}
}
}
} while (!q.empty());
}
int main() {
n = read();
m = read();
for (int i = 1; i <= m; ++i) {
U[i] = read();
V[i] = read();
add_edge(V[i], U[i], 0);
add_edge(U[i], V[i], 1);
}
dfs1(n);
memset(vis, 0, sizeof(vis));
dfs2(1);
memset(vis, 0, sizeof(vis));
edge = 0;
memset(fst, 0, sizeof(fst));
for (int i = 1; i <= m; ++i) {
if (flag[U[i]] != 2 || flag[V[i]] != 2) continue;
add_edge(U[i], V[i], 2);
add_edge(V[i], U[i], -1);
}
SPFA();
puts("Yes");
for (int i = 1; i <= m; ++i) {
if (flag[U[i]] != 2 || flag[V[i]] != 2) printf("1\n");
else printf("%d\n", dist[V[i]] - dist[U[i]]);
}
return 0;
}