ccf 201509-4 高速公路 (100分)

问题描述

  某国有n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路。
  现在,大臣们帮国王拟了一个修高速公路的计划。看了计划后,国王发现,有些城市之间可以通过高速公路直接(不经过其他城市)或间接(经过一个或多个其他城市)到达,而有的却不能。如果城市A可以通过高速公路到达城市B,而且城市B也可以通过高速公路到达城市A,则这两个城市被称为便利城市对。
  国王想知道,在大臣们给他的计划中,有多少个便利城市对。

输入格式

  输入的第一行包含两个整数n, m,分别表示城市和单向高速公路的数量。
  接下来m行,每行两个整数a, b,表示城市a有一条单向的高速公路连向城市b。

输出格式

  输出一行,包含一个整数,表示便利城市对的数量。

样例输入

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

样例输出

3

样例说明

这里写图片描述
  城市间的连接如图所示。有3个便利城市对,它们分别是(2, 3), (2, 4), (3, 4),请注意(2, 3)和(3, 2)看成同一个便利城市对。

评测用例规模与约定

  前30%的评测用例满足1 ≤ n ≤ 100, 1 ≤ m ≤ 1000;
  前60%的评测用例满足1 ≤ n ≤ 1000, 1 ≤ m ≤ 10000;
  所有评测用例满足1 ≤ n ≤ 10000, 1 ≤ m ≤ 100000。
   用Tarjan算法求出每个强连通分量的点数n,城市总数city+=(n-1)*n/2。
   提交后的100分的C++程序如下:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
using namespace std;
const int maxn = 10005;
vector<int> g[maxn];
stack<int> s;
int dfs_clock, sccno[maxn], scc_no, pre[maxn], low[maxn];
void dfs(int u) //找强连通分量
{
    pre[u] = low[u] = ++dfs_clock;
    s.push(u);
    for (int i = 0; i < (int)g[u].size(); i++)
    {
        int v = g[u][i];
        if (!pre[v])
        {
            dfs(v);
            low[u] = min(low[u], low[v]);
        }
        else if (!sccno[v])
        {
            low[u] = min(low[u], pre[v]);
        }
    }
    if (pre[u] == low[u])
    {
        scc_no++;
        while (true)
        {
            int x = s.top();
            s.pop();
            sccno[x] = scc_no;
            if (x == u) break;
        }
    }
}
int main()
{
    int n, m;
    cin >> n >> m;
    int src, dest;
    for (int i = 1; i <= m; i++)
    {
        cin >> src >> dest;
        g[src].push_back(dest);
    }
    memset(sccno, 0, sizeof(sccno));
    memset(pre, 0, sizeof(pre));
    memset(low, 0, sizeof(low));
    dfs_clock = 0, scc_no = 0;
    for (int i = 1; i <= n; i++)
    {
        if (!pre[i]) dfs(i);
    }
    int sum[maxn]; //每个强连通分量点的总数
    memset(sum, 0, sizeof(sum));
    for (int i = 1; i <= n; i++)
    {
        sum[sccno[i]]++;
    }
    int city = 0;//便利城市对的总数
    for (int i = 1; i <= scc_no; i++)
    {
        city += (sum[i] - 1)*sum[i] / 2;
    }
    cout << city << endl;
}

猜你喜欢

转载自blog.csdn.net/jinduo16/article/details/82081169
今日推荐