写代码是一种艺术,甚于蒙娜丽莎的微笑!

不拼搏,枉少年!

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
试题编号: 201509-4
试题名称: 高速公路
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  某国有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算法,关于tarjan算法可以阅读tarjan算法-解决有向图中求强连通分量的利器这篇文章。

不多说,上代码:

#include "Stdafx.h"
#include <iostream>
#include <stack>
using namespace std;

#define MAX_VERTEX_SIZE 10001
struct EdgeNode{
    int vertex;
    EdgeNode *nextArc;
};

struct VerTexNode{
    EdgeNode* firstArc;
};

struct Graph{
    int n,e;
    VerTexNode vNode[MAX_VERTEX_SIZE];
};

int time = 0;
int low[MAX_VERTEX_SIZE];
int dfn[MAX_VERTEX_SIZE];
int visited[MAX_VERTEX_SIZE];
int inStack[MAX_VERTEX_SIZE];
int ans = 0;//存储运算结果
stack<int> st;
Graph graph;

void initeGraph(int n,int m)
{
    for(int i = 1;i<=n;i++)
    {
        graph.vNode[i].firstArc = NULL;
    }
    graph.n = n;
    graph.e = m;

}

//头插法建立图
void creatGraph(int s,int v)
{
    EdgeNode *edgeNode = new EdgeNode;
    edgeNode->vertex = v;
    edgeNode->nextArc = graph.vNode[s].firstArc;
    graph.vNode[s].firstArc = edgeNode;
}    

int min(int a,int b)
{
    if(a>b)
        return b;
    else
        return a;
}

void trajan(int u)
{
    dfn[u] = low[u] = time++;
    st.push(u);
    visited[u] = 1;
    inStack[u] = 1;
    EdgeNode *edgePtr = graph.vNode[u].firstArc;
    while(edgePtr !=NULL)
    {
        int v = edgePtr->vertex;
        if(visited[v] == 0)
        {
            trajan(v);
            low[u] = min(low[u],low[v]);
        }
        /*之前没有对inStack[v]进行判断,又可能当前的v已经出栈了,这个时候就会出错。
        所以导致我的最后得分为80分。
        加上if条件,最后为满分。
        切记!切记!切记!!!
        */

        else if(inStack[v] == 1)
        {
            low[u] = min(low[u],dfn[v]);
        }
        edgePtr = edgePtr->nextArc;
    }

    int result = 0;
    if(dfn[u] == low[u])
    {
        int vtx;
        //cout<<"set is: ";
        do{
            result++;
            vtx = st.top();
            st.pop();
            inStack[vtx] = 0;//表示已经出栈
        /*    cout<<vtx<<' ';*/
        }while(vtx !=u );
        if(result > 1)
        {
            ans += result*(result-1)/2;
        }
        result = 0;
    }

}

int main()
{
    int n,m;
    int s,a;
    cin>>n>>m;
    initeGraph(n,m);
    for(int i = 1;i<=n;i++)
    {
        visited[i] = 0;
        inStack[i] = 0;
        dfn[i] = 0;
        low[i] = 0;
    }

    for(int j = 1;j<=m;j++)
    {
        cin>>s>>a;
        creatGraph(s,a);
    }

    for(int i =1;i<=n;i++)
        if(visited[i] == 0)
            trajan(i);
    cout<<ans<<endl;
    return 0;
}
View Code

 

posted on 2015-12-15 19:27  RunningSnail  阅读(609)  评论(0编辑  收藏  举报