图论第一次作业,不需要提交报告,在OJ上提交。

描述

Shrek是一个大山里的邮递员,每天负责给所在地区的n个村庄派发信件。但杯具的是,由于道路狭窄,年久失修,村庄间的道路都只能单向通过,甚至有些村庄无法从任意一个村庄到达。这样我们只能希望尽可能多的村庄可以收到投递的信件。

Shrek希望知道如何选定一个村庄A作为起点(我们将他空投到该村庄),依次经过尽可能多的村庄,路途中的每个村庄都经过仅一次,最终到达终点村庄B,完成整个送信过程。这个任务交给你来完成。

输入

第一行包括两个整数n,m,分别表示村庄的个数以及可以通行的道路的数目。

以下共m行,每行用两个整数v1和v2表示一条道路,两个整数分别为道路连接的村庄号,道路的方向为从v1至v2,n个村庄编号为[1, n]。

1 ≤ n ≤ 1,000,000

0 ≤ m ≤ 1,000,000

输入保证道路之间没有形成环

输出

输出一个数字,表示符合条件的最长道路经过的村庄数。

输入样例 1

4 3
1 4
2 4
4 3

输出样例 1

3

代码

先进性拓扑排序,之后dp找到最大值。

#include<iostream>
using namespace std;
#define myMax(x,y) ((x) > (y) ? (x) : (y))
int inDeg[1000005] = {0};   //入度 用于拓扑排序
int tpSorted[1000005] = {0};    //拓扑排序的顺序

//单个村庄
struct village{
    int id;
    village * next_village;
    village(int _id, village* next = NULL):id(_id),next_village(next){}
};

struct villages{
    village* _next;
    int dp; //直接写入属性
    villages():_next(NULL), dp(1){}
    void add(int next_id);
}Villages[1000005];

void villages::add(int next_id){
    inDeg[next_id] ++;
    if(!_next){
        _next = new village(next_id);
    }
    else{
        _next = new village(next_id, _next);
    }
}

//全局变量真好用...
int topologicalSort(int n){
    int res = 0;    //记录最大值
    int size = 0;   //拓扑数组长度
    for(int i = 1; i <= n; i++)
        if(!inDeg[i])
            tpSorted[size++] = i;
    
    //对数组进行操作
    for(int i = 0; i < size; i++){
        village* cur = Villages[tpSorted[i]]._next;
        while(cur){
            Villages[cur->id].dp = myMax(Villages[tpSorted[i]].dp+1, Villages[cur->id].dp);
            res = myMax(Villages[cur->id].dp, res);

            inDeg[cur->id]--;
            if(!inDeg[cur->id])
                tpSorted[size++] = cur->id;
            cur = cur->next_village;
        }
    }
    return res;
}
int main(){
    int n, m, v1, v2;
    cin >> n >> m;
    while(m--){
        cin >> v1 >> v2;
        Villages[v1].add(v2);        
    }
    cout << topologicalSort(n) << endl;
    return 0;
}