POJ 3694 Network(無向圖求橋的個數,有重邊)


Description:

A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are connected directly or indirectly by successive links, so data can be transformed between any two computers. The administrator finds that some links are vital to the network, because failure of any one of them can cause that data can't be transformed between some computers. He call such a link a bridge. He is planning to add some new links one by one to eliminate all bridges.

You are to help the administrator by reporting the number of bridges in the network after each new link is added.

Input:

The input consists of multiple test cases. Each test case starts with a line containing two integers N(1 ≤ N ≤ 100,000) and M(N - 1 ≤ M ≤ 200,000).
Each of the following M lines contains two integers A and B ( 1≤ A ≠ B ≤ N), which indicates a link between computer A and B. Computers are numbered from 1 to N. It is guaranteed that any two computers are connected in the initial network.
The next line contains a single integer Q ( 1 ≤ Q ≤ 1,000), which is the number of new links the administrator plans to add to the network one by one.
The i-th line of the following Q lines contains two integer A and B (1 ≤ A ≠ B ≤ N), which is the i-th added new link connecting computer A and B.

The last test case is followed by a line containing two zeros.

Output:

For each test case, print a line containing the test case number( beginning with 1) and Q lines, the i-th of which contains a integer indicating the number of bridges in the network after the first i new links are added. Print a blank line after the output for each test case.

Sample Input:

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

Sample Output

Case 1:
1
0

Case 2:
2
0

題意:有n台電腦,它們之間是互相連通的,現在有Q次查詢,每次查詢時,又給該網絡增加了一次連接,問有了這次連接之后,該網絡有幾座橋(必不可少的邊)

由於直接統計邊很不方便,所以可以統計每條邊的終點,以此代替邊

Tarjan函數:求出了以v為終點的邊的個數,以及最初的網絡中橋的個數
LCR函數:在找到與添加的邊的終點相同的橋時,橋的個數需要減1,依次遞歸,直至這條邊的兩個端點相同,求出最終橋的個數

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#define N 100010
using namespace std;
int dfn[N], low[N];
int f[N], bri[N]; //bri數組統計終點一樣的邊的個數,由於邊不便統計,所以,以該數組下標為邊的終點來代替橋
int Time, ans, n; //ans統計橋的個數
vector<vector<int> >G;
void Init()
{
    G.clear();
    G.resize(n+1);
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(f, 0, sizeof(f));
    memset(bri, 0, sizeof(bri));
    Time = ans = 0;
}
void Tarjan(int u, int fa)
{
    int i, len, v;
    dfn[u] = low[u] = ++Time;
    f[u] = fa;
    len = G[u].size();
    for (i = 0; i < len; i++)
    {
        v = G[u][i];
        if (!dfn[v])
        {
            Tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (dfn[u] < low[v])
            {
                bri[v]++; //說明邊終點為v的個數
                ans++; //該點之前沒有遍歷過,說明該邊可能是橋
            }
        }
        else if (v != fa)
        {
            low[u] = min(low[u], dfn[v]);
            if (dfn[u] < low[v])
            {
                bri[v]++;
                ans--; //該點之前被遍歷過,說明還有其他路徑可以達到此點,則該邊不是橋
            }
        }
    }
}
void LCR(int a, int b)
{
    if (a == b) return ; //兩個點相同時不需要再進行
    if (dfn[a] < dfn[b])
    {
        if (bri[b] == 1) //如果終點為b的邊只有一條,那么它肯定是橋,現在又加了一條終點為b的邊,那么以b為終點的邊就不是橋了,ans--
        {
            bri[b] = 0;
            ans--;
        }
        LCR(a, f[b]); //dfn[a] < dfn[b]說明a點比b點更早遍歷,那么下次就應該比較a和b的父節點,因為父節點總是比子節點更早的遍歷
    }
    else
    {
        if (bri[a] == 1)
        {
            bri[a] = 0;
            ans--;
        }
        LCR(f[a], b);
    }
}
int main ()
{
    int m, q, a, b, k = 0;
    while (scanf("%d%d", &n, &m), n+m)
    {
        Init();
        k++;
        while (m--)
        {
            scanf("%d%d", &a, &b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        Tarjan(1, 0);
        scanf("%d", &q);
        printf("Case %d:\n", k);
        while (q--)
        {
            scanf("%d%d", &a, &b);
            LCR(a, b);
            printf("%d\n", ans);
        }
        printf("\n");
    }
    return 0;
}

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: