[HDU5385]The path 题解

[HDU5385]The path 题解

题目地址:HDUOJ:Problem – 5385

题目描述

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.
给你一个有向图,你要确定每条边的边权,使得存在1到每个点的最短路距离d满足d(1)<d(2)<….d(x)>d(x+1)>…d(n)。

输入输出格式

输入格式:
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∗10^5,∑m≤6∗10^5
1≤n,m≤10^5

输出格式:
For each test case,print m lines.The i-th line includes one integer:the length of edge from ui to vi

输入输出样例

输入样例#1:

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

输出样例#1:

1
2
2
1
4
4
1
1
3
4
4
4

题解

其实这道题如果能想到Prim算法的流程就好做了。Prim是确定一个点的d为0,然后向外扩展到当前选定点集距离最小的点,扩展完毕以后就是一棵最短路树/最小生成树。那么我们也来构造这样一棵最短路树/最小生成树,使得树边满足题目要求且非树边边权极大就可以了。
我们确定1为树根,d(1)=0,然后从最小号点和最大号点开始往里加点,每加一个点就给它的出边和相邻点打标记,表示这些边/点以后应当计算。
虽然数据范围长得很像O(n \log n),但其实算法是O(m)的。

代码

// Code by KSkun, 2018/3
#include <cstdio>
#include <cstring>

#include <vector>
#include <algorithm>

typedef long long LL;

inline char fgc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

inline LL readint() {
    register LL res = 0, neg = 1;
    char c = fgc();
    while(c < '0' || c > '9') {
        if(c == '-') neg = -1;
        c = fgc();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = fgc();
    }
    return res * neg;
}

const int MAXN = 600005;

struct Edge {
    int u, v, id;
};

int T, n, m, ut, vt, dis[MAXN];
std::vector<Edge> gra[MAXN], edges;
bool vis[MAXN], ans[MAXN];

inline void work(int u, int d) {
    dis[u] = d;
    for(int i = 0; i < gra[u].size(); i++) {
        int v = gra[u][i].v;
        if(vis[v]) continue;
        vis[v] = true;
        ans[gra[u][i].id] = true;
    }
}

int main() {
    T = readint();
    while(T--) {
        n = readint(); m = readint();
        memset(dis, 0, sizeof(dis));
        memset(ans, 0, sizeof(ans));
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; i++) gra[i].clear();
        edges.clear();
        for(int i = 1; i <= m; i++) {
            ut = readint(); vt = readint();
            gra[ut].push_back(Edge {ut, vt, i});
            edges.push_back(Edge {ut, vt, i});
        }
        int l = 1, r = n, d = 0;
        vis[l] = true;
        while(l <= r) {
            if(vis[l]) work(l++, d++);
            if(vis[r]) work(r--, d++);
        }
        for(int i = 1; i <= m; i++) {
            if(ans[i]) {
                printf("%d\n", std::abs(dis[edges[i - 1].u] - dis[edges[i - 1].v]));
            } else {
                printf("%d\n", n);
            }
        }
    }
    return 0;
}


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据