## hdu 5385 The path ##
Problem Description
You have a connected directed graph.Let d(x) be the length of the shortest path from 1 to x.Specially d(1)=0.A graph is good if there exist x satisfy d(1) < d(2) < ….d(x) > d(x+1) > …d(n).Now you need to set the length of every edge satisfy that the graph is good.Specially,if d(1) < d(2) < ..d(n),the graph is good too.
The length of one edge must ∈ [1,n]
It’s guaranteed that there exists solution.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains two integers n and m,the number of vertexs and the number of edges.Next m lines contain two integers each, ui and vi (1≤ui,vi≤n), indicating there is a link between nodes ui and vi and the direction is from ui to vi.
∑n≤3∗105,∑m≤6∗105
1≤n,m≤105
Output
For each test case,print m lines.The i-th line includes one integer:the length of edge from ui to vi
Sample Input
2
4 6
1 2
2 4
1 3
1 2
2 2
2 3
4 6
1 2
2 3
1 4
2 1
2 1
2 1
Sample Output
1
2
2
1
4
4
1
1
3
4
4
4
题目大意:一张图有N个顶点,给出一些有向边,问该如何给这些边赋值才能满足d(1) < d(2) < ….d(x) > d(x+1) > …d(n) 的条件且1为起点,d(x)表示1到x的最短距离. 赋值的范围在1~N。
解题思路:左边从2开始,右边从n开始,每次选与之前标记过的点相连的未标记过得点,该点的d[i]为该点加入的时间。最后输出时,判断该点是否在最短路上,不在的话,输出n,在的话输出d[v] - d[u]。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
const int N = 300005;
const int M = 600005;
typedef long long ll;
int n, m;
int head[M], vis[N];
int d[M], ec;
struct Edge{
int from, to, next;
}edges[M];
void addEdge(int u, int v) {
edges[ec].from = u;
edges[ec].to = v;
edges[ec].next = head[u];
head[u] = ec++;
}
void init() {
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
ec = 0;
d[1] = 0;
d[2] = 1;
d[n] = 1;
vis[1] = -1;
}
void mark(int u) { //标记已标记点u所相连的未标记的点
for (int i = head[u]; i != -1; i = edges[i].next) {
int v = edges[i].to;
if (!vis[v]) vis[v] = u;
}
}
void input() {
int a, b;
scanf("%d %d", &n, &m);
for (int i = 0; i < m; i++) {
scanf("%d %d", &a, &b);
addEdge(a, b);
}
}
void solve() {
int l = 1, r = n, val = 1;
while (l <= r) { //从2和n开始加点,d[i]为点i加入的时间
if (vis[l]) {
mark(l);
d[l++] = val++;
}
if (vis[r]) {
mark(r);
d[r--] = val++;
}
}
for (int i = 0; i < ec; i++) {
int u = edges[i].from, v = edges[i].to;
if (vis[v] != u) printf("%d\n", n); //不在最短路树上的边
else printf("%d\n", d[v] - d[u]); //最短路树上的边
}
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
init();
input();
solve();
}
return 0;
}