基環樹上求環


題目描述

A subway scheme, classic for all Berland cities is represented by a set of n stations connected by n passages, each of which connects exactly two stations and does not pass through any others. Besides, in the classic scheme one can get from any station to any other one along the passages. The passages can be used to move in both directions. Between each pair of stations there is no more than one passage.

Berland mathematicians have recently proved a theorem that states that any classic scheme has a ringroad. There can be only one ringroad. In other words, in any classic scheme one can find the only scheme consisting of stations (where any two neighbouring ones are linked by a passage) and this cycle doesn't contain any station more than once.

This invention had a powerful social impact as now the stations could be compared according to their distance from the ringroad. For example, a citizen could say "I live in three passages from the ringroad" and another one could reply "you loser, I live in one passage from the ringroad". The Internet soon got filled with applications that promised to count the distance from the station to the ringroad (send a text message to a short number...).

The Berland government decided to put an end to these disturbances and start to control the situation. You are requested to write a program that can determine the remoteness from the ringroad for each station by the city subway scheme.

題目大意:求基環樹上和環之間的最短距離。

輸入輸出格式

輸入格式:

 

The first line contains an integer n (3 ≤ n ≤ 3000), n is the number of stations (and trains at the same time) in the subway scheme. Then n lines contain descriptions of the trains, one per line. Each line contains a pair of integers xi, yi (1 ≤ xi, yi ≤ n) and represents the presence of a passage from station xi to station yi. The stations are numbered from 1 to n in an arbitrary order. It is guaranteed thatxi ≠ yi and that no pair of stations contain more than one passage. The passages can be used to travel both ways. It is guaranteed that the given description represents a classic subway scheme.

 

輸出格式:

 

Print n numbers. Separate the numbers by spaces, the i-th one should be equal to the distance of the i-th station from the ringroad. For the ringroad stations print number 0.

題解

基環樹:又稱環套樹,指的是由n個點和n條邊組成的任意兩點間都連通的圖,比樹多一條邊,所以整個圖中有且只有一個環。

在基環樹上找環,我們可以通過一邊DFS,在遍歷過程中對於一條邊所到達的點已經被訪問過,且不是這條邊的出發點則證明這條邊在環上。而這條邊的終點V上一次到這一次之間所經過的點連成路徑便是一個環,而這個路徑們可以通過棧來記錄。

值得注意的是,一遍DFS只能求出一個環,而再求出環之后的DFS需要把這個環縮成一個點之后才能正常進行,這也是這個方法比較低效的方法。

代碼

#include <bits/stdc++.h>
using namespace std;

const int MAX = 3005;
int Head[MAX], Next[MAX << 1], To[MAX << 1], w[MAX << 1], edgenum = 0;
void Add_edge(int from, int to)
    {
        Next[++ edgenum] = Head[from];
        Head[from] = edgenum;
        To[edgenum] = to;
    }

int sta[MAX], top = 0, vis[MAX], huan[MAX], cnthuan = 0, flag;
void Get_huan(int u, int father)
    {
        if(flag) return;
        sta[++ top] = u, vis[u] = 1;
        for(int i = Head[u]; i != -1; i = Next[i])
        {
            int v = To[i];
            if(v == father)    continue;
            if(vis[v])    //有環
            {
                huan[v] = ++cnthuan;
                for(;sta[top] != v; -- top)    huan[sta[top]] = cnthuan;
                top --;
                flag = 1;
                return;
            }
            Get_huan(v, u);
            sta[-- top], vis[v] = 0;
        }
        return;
    }

int Deep[MAX];
void Get_Deep(int u)
    {
        for(int i = Head[u]; i != -1; i = Next[i])
        {
            int v = To[i];
            if(Deep[v] || huan[v])    continue;
            Deep[v] = Deep[u] + 1;
            Get_Deep(v);
        }
    }

int main()
{
    //freopen("CF131D.in", "r", stdin);
    //freopen("CF131D.out", "w", stdout);

    int n, x, y, colorhuan;
    memset(Head, -1, sizeof(Head));
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i)
    {
        scanf("%d%d", &x, &y);
        Add_edge(x, y);
        Add_edge(y, x);
    }
    flag = 0;
    Get_huan(1, 0);
    for(int i = 1; i <= n; ++ i)
    {
        if(huan[i] != 0)
        {
            Deep[i] = 0;
            Get_Deep(i);
        }
    }
    for(int i = 1; i <= n; ++ i)    printf("%d ", Deep[i]);
    printf("\n");
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM