题目来源:
http://www.patest.cn/contests/mooc-ds/06-%E5%9B%BE8
解:
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();//点数
int M = scanner.nextInt();//边数
int[][] adjacency =new int[N+1][N+1]; //邻接表
int[] indegree= new int[N+1];//节点的入度
int[] outdegree = new int[N+1]; //节点的出度
int[] visit= new int[N+1];//访问标志
int[] lcost =new int[N+1];//最迟开始实践
int[] ecost = new int[N+1];//最早开始时间
int max =0;//最大值的下标
ArrayList<Integer> list = new ArrayList<Integer>();//存储关键路径
Arrays.fill(indegree, 0);
Arrays.fill(outdegree, 0);
Arrays.fill(visit, 0);
Arrays.fill(lcost, 0);
Arrays.fill(ecost, Integer.MAX_VALUE);
for(int i=1;i<=N;++i)
Arrays.fill(adjacency[i],Integer.MAX_VALUE);
//M次循环输入
for(int i=1;i<=M;i++)
{
int start = scanner.nextInt();
int end = scanner.nextInt();
int cost = scanner.nextInt();
adjacency[start][end]=cost;
indegree[end]++;
outdegree[start]++;
}
//计算关键路径长度
//计算最晚开始时间
for(int j=1;j<=N;++j)
{
int index =getZeroDegreeIndex(indegree,visit);
if(index==-1)//没有度为0的点
{
System.out.println(0);
return ;
}
else
{
int[] adj = adjacency[index]; //遍历节点index连接的所有节点
for(int i=1;i<=N;++i)
{
if(adj[i]!=Integer.MAX_VALUE ) //如果可达
{
indegree[i]--;
if(lcost[i] <lcost[index]+adj[i])
{
lcost[i] = lcost[index]+adj[i];
if(lcost[max]<lcost[i])
max=i;
}
}
}
}
}
//计算最早开始时间
Arrays.fill(visit, 0);
ecost[max]=lcost[max];
for(int j=1;j<=N;++j)
{
int index =getZeroDegreeIndex(outdegree,visit);
if(index==-1)//没有度为0的点
{
System.out.println(0);
return ;
}
else
{
//遍历第index列
for(int i=1;i<=N;++i)
{
int temp = adjacency[i][index];
if(temp!=Integer.MAX_VALUE ) //如果可达
{
outdegree[i]--;
if(ecost[i] > ecost[index]-temp)
{
ecost[i] = ecost[index]-temp;
}
}
}
}
}
System.out.println(lcost[max]);
// 最早开始时间=最晚开始时间的为关键路径节点
for(int i=1 ;i<=N;i++)
{
if(lcost[i]==ecost[i])
list.add(i);
}
for(int i=1;i<=N;i++)
{
if(list.contains(i))
{
for(int j=N;j>=1;--j)
{
if(list.contains(j) && ecost[j]==ecost[i]+adjacency[i][j]) //如果可达
{
System.out.println(i+"->"+j);
}
}
}
}
}
/*寻找入度为0的点的下标
* */
public static int getZeroDegreeIndex(int[] degree,int[] visit)
{
for(int i=1;i<degree.length;++i)
{
if(degree[i]==0 && visit[i]==0)
{
visit[i]=1;
return i;
}
}
return -1;
}
}