题目传送门:Luogu P5590
Description
给定一些有向边,对它们赋上边权 w ∈ [ 1 , 9 ] w\in [1,9] w∈[1,9] ,使得每条 1 → n 1\to n 1→n 的简单路径长相等。
Solution
差分约束。
对于每条通往终点的遍,加边add(b, a, -1), add(a, b, 9)
。
如何判断与终点连通?dfs一遍就可以了。
然后跑差分约束,输出 dis 。
Code
/*
* @Name: P5590 赛车游戏
* @Author: Lovely_XianShen
* @Date: 2019-10-30 12:32:10
* @Aqours!Sunshine!!
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 10000 + 5;
inline int read() {
int a = 0; char x = getchar();
while (x < '0' || x > '9')x = getchar();
while (x >= '0' && x <= '9')a = (a << 3) + (a << 1) + x - 48, x = getchar();
return a;
}
int n, m;
int tot, head[N], tot1, head1[N];
struct node {
int to, nxt, val;
} e[N << 4], e1[N << 4];
inline void add(int x, int y) {
e[++tot].nxt = head[x];
head[x] = tot;
e[tot].to = y;
}
inline void add1(int x, int y, int z) {
e1[++tot1].nxt = head1[x];
head1[x] = tot1;
e1[tot1].val = z;
e1[tot1].to = y;
}
bool vis[N], p[N];
int dis[N];
int cnt[N];
bool spfa() {
memset(vis, 0, sizeof vis);
memset(dis, 0x3f, sizeof dis);
queue<int> q;
q.push(0);
dis[0] = 0;
vis[0] = 1;
while (!q.empty()) {
int now = q.front();
q.pop();
vis[now] = 0;
for (int i = head1[now]; i; i = e1[i].nxt)
if (dis[now] + e1[i].val < dis[e1[i].to]) {
int y = e1[i].to;
dis[y] = dis[now] + e1[i].val;
cnt[y] = cnt[now] + 1;
if (cnt[y] > n)
return 1;
if (!vis[y])
q.push(y), vis[y] = 1;
}
}
return 0;
}
bool dfs(int x) {
if (x == n || p[x])
return 1;
bool flag = 0;
vis[x] = 1;
for (int i = head[x]; i; i = e[i].nxt)
if (!vis[e[i].to])
if (dfs(e[i].to))
add1(x, e[i].to, 9), add1(e[i].to, x, -1), flag = 1;
vis[x] = 0;
p[x] = flag;
return p[x];
}
int x[N << 1], y[N << 1];
int main() {
n = read();
m = read();
for (int i = 1; i <= m; i++) {
int a, b;
a = read();
b = read();
x[i] = a;
y[i] = b;
add(a, b);
}
for (int i = 1; i <= n; i++)
add1(0, i, 0);
if (!dfs(1) || spfa()) {
puts("-1");
return 0;
}
cout << n << " " << m << endl;
for (int i = 1; i <= m; i++) {
cout << x[i] << " " << y[i] << " ";
int aqours = dis[x[i]] - dis[y[i]];
if (aqours < 0)
aqours = -aqours;
if (aqours > 0 && aqours <= 9)
cout << aqours << endl;
else
cout << 1 << endl;
}
return 0;
}