//らせん階段 // カブト虫 // 廃墟の街 // イチジクのタルト // カブト虫 //ドロローサへの道 // カブト虫 // 特異点 // ジョット // エンジェル // 紫陽花 // カブト虫 // 特異点 // 秘密の皇帝 #include #include #include #include // tree, rb_tree_tag, tree_order_statistics_node_update> S; // #include // using namespace boost::multiprecision; using namespace std; using namespace __gnu_pbds; using namespace atcoder; // ↓変数の値はA.val()で取得する using mint9 = modint998244353; using mint7 = modint1000000007; #define ll long long #define ld long double #define pi pair #define PQ priority_queue #define PQG priority_queue, greater> #define MV(V,N) vector (V)(N); for (int i=0;i<(N);i++) cin >>V[i]; #define vi vector #define vld vector #define vs vector #define vp vector #define vvi(V,H,W) vector> (V)((H),vector(W)); #define vvl(V,H,W) vector> (V)((H),vector(W)); #define vvld(V,H,W) vector> (V)((H),vector(W)); #define vvs(V,H,W) vector> (V)((H),vector(W)); #define vvc(V,H,W) vector> (V)((H),vector(W)); #define checkV(V) for (auto x:V) cout<=(e);(i)--) #define INF 1000000000000000000 #define PI 3.14159265358979323846264338327950288 #define Banpei 1000000000 //問題毎に設定 #define Max_V 100000 #define mod7 1000000007 #define mod9 998244353 #define eps 0.00000001 #define ALL(V,A) ((V).begin(),(V).end(),(A)) #define Find(V,X) find(V.begin(),V.end(),X) #define Lbound(V,X) *lower_bound((V).begin(),(V).end(),(X)) #define LboundP(V,X) lower_bound((V).begin(),(V).end(),(X))-(V).begin(); #define Ubound(V,X) *upper_bound((V).begin(),(V).end(),(X)) #define UboundP(V,X) upper_bound((V).begin(),(V).end(),(X))-(V).begin(); #define Sort(V) sort((V).begin(),(V).end()) #define SortPairBySecond(V) sort((V).begin(), (V).end(), [](auto a, auto b) { return a.second < b.second; }); #define Reverse(V) reverse((V).begin(),(V).end()) #define Greater(V) sort((V).begin(),(V).end(),greater()) #define cmin(ans,A) (ans)=min((ans),(A)) #define cmax(ans,A) (ans)=max((ans),(A)) #define AUTO(x,V) for (auto (x):(V)) #define int long long //fixed << setprecision(10) << using Graph = vector>; Graph makeGraph(int N, int V) { Graph G(N); irep (V) { int A,B; cin >>A>>B; A--;B--; G[A].push_back(B); G[B].push_back(A); } return G; } struct UnionFind { //0オリジンに修正して使用 vector size, parents; UnionFind() {} UnionFind(int n) { // make n trees. size.resize(n, 0); parents.resize(n, 0); for (int i = 0; i < n; i++) { makeTree(i); } } void makeTree(int x) { parents[x] = x; // the parent of x is x size[x] = 1; } bool isSame(int x, int y) { return findRoot(x) == findRoot(y); } bool unite(int x, int y) { x = findRoot(x); y = findRoot(y); if (x == y) return false; if (size[x] > size[y]) { parents[y] = x; size[x] += size[y]; } else { parents[x] = y; size[y] += size[x]; } return true; } int findRoot(int x) { if (x != parents[x]) { parents[x] = findRoot(parents[x]); } return parents[x]; } int treeSize(int x) { return size[findRoot(x)]; } }; signed main() { int N,M; cin >>N >>M; UnionFind UF=UnionFind(N); vp V(M); irep(M) cin >>V[i].first>>V[i].second; Reverse(V); vi dp(N); irep(M) { int A=V[i].first,B=V[i].second; A--;B--; int C=UF.findRoot(A),D=UF.findRoot(B); int stock=max(dp[C],dp[D])+1; UF.unite(A,B); dp[UF.findRoot(A)]=stock; } cout<