题目:
思路:
本题是一个典型的有向图求强连通分量的题目,求得强连通分量后,对每个强连通分量中的结点进行统计,最后将每个强连通分量的城市对的组合数相加就是最后答案。这里我使用的是Kosaraju算法求得得强连通分量。
Kosaraju算法分为两个步骤:
(1)对原图进行DFS遍历,求得该图得逆后序遍历顺序;
(2)将原图取反,按照第一步取得得遍历顺序对图进行DFS遍历,每次DFS遍历中得结点即属于一个强连通分量。
关于Kosaraju算法,有个不错得博客,详情见https://www.cnblogs.com/nullzx/p/6437926.html。
代码:
import java.util.*;
public class Main {
public static void dfs(Vertex vertex,int[] visit,Stack<Vertex> stack){
int num = vertex.num;
if(visit[num]==0){
visit[num]=1;
for(int i=0;i<vertex.edgeTo.size();i++){
dfs(vertex.edgeTo.get(i).vertexTo,visit,stack);
}
stack.push(vertex);
}
}
public static int Combination(int n, int m)
{
int ans = 1;
for(int i=n; i>=(n-m+1); --i)
ans *= i;
while(m!=0)
ans /= m--;
return ans;
}
public static void rdfs(Vertex vertex,int[] visit,int level){
int num = vertex.num;
if(visit[num]==0){
visit[num]=1;
vertex.level = level;
for(int i=0;i<vertex.edgeFrom.size();i++){
rdfs(vertex.edgeFrom.get(i).vertexTo,visit,level);
}
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
List<Vertex> list = new ArrayList<Vertex>();
for(int i=0;i<n;i++){
Vertex vertex = new Vertex(i);
list.add(vertex);
}
for(int i=0;i<m;i++){
int a = sc.nextInt();
int b = sc.nextInt();
Vertex vertexStart = list.get(a-1);
Vertex vertexEND = list.get(b-1);
Edge edge = new Edge(vertexStart,vertexEND);
Edge edge1 = new Edge(vertexEND,vertexStart);
vertexStart.edgeTo.add(edge);
vertexEND.edgeFrom.add(edge1);
}
int[] visit = new int[n];
for(int i=0;i<n;i++){
visit[i]=0;
}
Stack<Vertex> stack = new Stack<Vertex>();
for (int i=0;i<n;i++){
if(visit[i]==0){
dfs(list.get(i),visit,stack);
}
}
for(int i=0;i<n;i++){
visit[i]=0;
}
int count=0;
while(!stack.empty()){
Vertex vertex = stack.pop();
//System.out.println(visit[vertex.num]);
if(visit[vertex.num]==0){
rdfs(vertex,visit,count);
count++;
}
}
int res=0;
for(int i=0;i<count;i++){
// System.out.println(list.get(i).level);
int temp=0;
for(int j=0;j<list.size();j++){
if(list.get(j).level==i){
temp++;
}
}
if(temp>=2)
res+=Combination(temp,2);
}
System.out.println(res);
}
}
class Vertex{
List<Edge> edgeTo;
List<Edge> edgeFrom;
int num;
int level;
public Vertex(int num){
this.num = num;
edgeTo = new ArrayList<Edge>();
edgeFrom = new ArrayList<Edge>();
}
}
class Edge{
Vertex vertexFrom;
Vertex vertexTo;
public Edge(Vertex vertexFrom,Vertex vertexTo){
this.vertexFrom = vertexFrom;
this.vertexTo = vertexTo;
}
}