有向无环图最长路径java_有向无环图的最长简单路径

本文介绍了如何使用动态规划求解有向无环图(DAG)中从节点k到节点t的最长简单路径。讨论了算法的最优子结构和重叠子结构,并提供了状态转移函数。通过创建和操作邻接矩阵,实现了图的构建和路径查找。文章还包含了算法的重构,以便输出最长路径的解决方案。
摘要由CSDN通过智能技术生成

给定一个有向无环图$G=(V,E)$,边权重为实数,给定图中的两个顶点$k,t$,设计动态规划算法,求从k到t的最长简单路径,子问题图是怎样的?算法的效率如何?

算法分析:

该问题不能够用贪心求解,假设从k出发,每一步取得weight最大的边,按这样的路径,并不能够保证能走到终点t。所以考虑动态规划算法。

该问题满足动态规划算法的两个特征:

一、最优子结构:

从k出发到t的最优路径,一定是$max(best , path , A_1 , to ,, t+weightA_0)$,其中$A0-->A1-->cdots t$和$B0-->B1-->cdots t$等等的诸多方案中的最优方案,构成了最优解。符合“剪贴”性质。

二、重叠子结构

有上面的公式可知,子问题:$A0-->A1-->cdots t$会被反复求解。

76b1281cb512932b995cc1b31a3c1a6b.png

状态转移函数:

int q=weight[k][t];

for(int i=k+1;i<=t && weight[k][i];i++)

{

q=max(q,weight[k][i]+Find_longest_path(weight,numVertexes,i,t,r));

}

r[k]=q;

return q;

算法实现

Graphic_longest_path.h

#include

#include

using namespace std;

#define INITWEIGHT 0

//用矩阵实现图

class graph

{

private:

bool isWeighted; //是否带权?

bool isDirected; //是否有向?

int numV; //顶点数

int numE; //边数

int **matrix; //邻接矩阵

public:

graph(int numV,bool isWeighted=false,bool isDirected=false);

void createGraph();

~graph();

int getVerNums()

{

return numV;

}

int getEdgeNums()

{

return numE;

}

int **getWeight()

{

return matrix;

}

void setEdgeWeight(int beg,int end,int weight);

void printAdjacentMatrix();

//检查输入

bool check(int i,int j,int w=1);

};

//类的实现

graph::graph(int numV,bool isWeighted,bool isDirected)

{

while(numV<=0)

{

cout<

cin>>numV;

}

this->numV=numV;

this->isWeighted=isWeighted;

this->isDirected=isDirected;

//private之后的成员可以被类的成员函数访问,但是不能够被使用该类的代码访问

matrix=new int *[numV];

for(int i=0;i

matrix[i]=new int [numV];

//对图进行初始化

if(!isWeighted) //无权图

{

//对所有的权值初始化为0

for(int i=0;i

for(int j=0;j

matrix[i][j]=0;

}

else //有权图

{

for(int i=0;i

for(int j=0;j

matrix[i][j]=INITWEIGHT;

}

}

//建图

void graph::createGraph()

{

cout<

while(cin>>numE && numE<0)

cout<

int i,j,w;

if(!isWeighted) //无权图

{

if(!isDirected) //无向图

{

cout<

for(int k=0;k

{

cin>>i>>j;

while(!check(i,j))

{

cout<

cin>>i>>j;

}

matrix[i][j]=matrix[j][i]=1;

}

}

else

{

cout<

for(int k=0;k

{

cin>>i>>j;

while(!check(i,j))

{

cout<

cin>>i>>j;

}

matrix[i][j]=1;

}

}

}

else //有权图

{

if(!isDirected) //无向图

{

cout<

for(int k=0;k

{

cin>>i>>j>>w;

while(!check(i,j,w))

{

cout<

cin>>i>>j>>w;

}

matrix[i][j]=matrix[j][i]=w;

}

}

else

{

cout<

for(int k=0;k

{

cin>>i>>j>>w;

while(!check(i,j,w))

{

cout<

cin>>i>>j>>w;

}

matrix[i][j]=w;

}

}

}

}

graph::~graph() //析构函数

{

for(int i=0;i

delete[] matrix[i];

delete[] matrix;

}

//设置指定边权值:

void graph::setEdgeWeight(int beg,int end,int weight)

{

if(isWeighted)

{

while(!check(beg,end,weight))

{

cout<

cin>>beg>>end>>weight;

}

if(isDirected)

matrix[beg][end]=weight;

else

matrix[beg][end]=matrix[end][beg]=weight;

}

else

{

while(!check(beg,end,1))

{

cout<

cin>>beg>>end;

}

if(isDirected) //对邻接矩阵的值进行反转,重置,1变成0,0变成1

matrix[beg][end]=1-matrix[beg][end];

else

matrix[beg][end]=matrix[end][beg]=1-matrix[beg][end];

}

}

//输入检查

bool graph::check(int i,int j,int w)

{

if(i>=0 && i=0 && j0)

return true;

else

return false;

}

void graph::printAdjacentMatrix()

{

cout.setf(ios::left);

cout<

for(int i=0;i

cout<

cout<

for(int i=0;i

{

cout<

for(int j=0;j

cout<

cout<

}

}

dynamic_longest_path.h

#include "Graphic_longest_path.h"

#include

#include

#define INFINITY 0x7fffffff

int max(int a,int b)

{

return a>b?a:b;

}

int Find_longest_path(int **weight,int numVertexes,int k,int t,vector &r) //寻找k到t的最短路径

{

if(r[k]>=0)

return r[k];

if(k==t)

{

int q=0;

r[k]=q;

return q;

}

else

{

int q=weight[k][t];

for(int i=k+1;i<=t && weight[k][i];i++)

{

q=max(q,weight[k][i]+Find_longest_path(weight,numVertexes,i,t,r));

}

r[k]=q;

return q;

}

}

int dynamic_longest_path(int **weight,int numVertexes,int k,int t)

{

vector r;

r.resize(numVertexes);

for(int i=0;i

r[i]=-INFINITY;

return Find_longest_path(weight,numVertexes,k,t,r);

}

Graphic_longest_path.cpp

#include "dynamic_longest_path.h"

#include

int main()

{

cout<

bool isDirected, isWeighted;

int numV;

cout<

cout<

cin>>numV;

cout<

cin>>isWeighted;

cout<

cin>>isDirected;

graph graph(numV,isWeighted,isDirected);

cout<

isDirected ? cout<

isWeighted ? cout<

graph.createGraph();

cout<

graph.printAdjacentMatrix();

cout<

int k,t;

cout<

cin>>k>>t;

int numVertex=graph.getVerNums();

int **weight_dynamic=graph.getWeight();

cout<

cout<

int result=dynamic_longest_path(weight_dynamic,numVertex,k,t);

cout<

cout<

int beg, end, weight;

bool flag;

cout<

cin>>flag;

if(flag)

{

if(isWeighted)

{

cout<

cin>>beg>>end>>weight;

graph.setEdgeWeight(beg,end,weight);

}

else

{

cout<

cin>>beg>>end;

graph.setEdgeWeight(beg,end,1);

}

cout<

cout<

graph.printAdjacentMatrix();

}

return 0;

}

重构解

为了能够输出最短路径的方案,可以对解进行重构:

Graphic_longest_path.h

#include

#include

using namespace std;

#define INITWEIGHT 0

//用矩阵实现图

class graph

{

private:

bool isWeighted; //是否带权?

bool isDirected; //是否有向?

int numV; //顶点数

int numE; //边数

int **matrix; //邻接矩阵

public:

graph(int numV,bool isWeighted=false,bool isDirected=false);

void createGraph();

~graph();

int getVerNums()

{

return numV;

}

int getEdgeNums()

{

return numE;

}

int **getWeight()

{

return matrix;

}

void setEdgeWeight(int beg,int end,int weight);

void printAdjacentMatrix();

//检查输入

bool check(int i,int j,int w=1);

};

//类的实现

graph::graph(int numV,bool isWeighted,bool isDirected)

{

while(numV<=0)

{

cout<

cin>>numV;

}

this->numV=numV;

this->isWeighted=isWeighted;

this->isDirected=isDirected;

//private之后的成员可以被类的成员函数访问,但是不能够被使用该类的代码访问

matrix=new int *[numV];

for(int i=0;i

matrix[i]=new int [numV];

//对图进行初始化

if(!isWeighted) //无权图

{

//对所有的权值初始化为0

for(int i=0;i

for(int j=0;j

matrix[i][j]=0;

}

else //有权图

{

for(int i=0;i

for(int j=0;j

matrix[i][j]=INITWEIGHT;

}

}

//建图

void graph::createGraph()

{

cout<

while(cin>>numE && numE<0)

cout<

int i,j,w;

if(!isWeighted) //无权图

{

if(!isDirected) //无向图

{

cout<

for(int k=0;k

{

cin>>i>>j;

while(!check(i,j))

{

cout<

cin>>i>>j;

}

matrix[i][j]=matrix[j][i]=1;

}

}

else

{

cout<

for(int k=0;k

{

cin>>i>>j;

while(!check(i,j))

{

cout<

cin>>i>>j;

}

matrix[i][j]=1;

}

}

}

else //有权图

{

if(!isDirected) //无向图

{

cout<

for(int k=0;k

{

cin>>i>>j>>w;

while(!check(i,j,w))

{

cout<

cin>>i>>j>>w;

}

matrix[i][j]=matrix[j][i]=w;

}

}

else

{

cout<

for(int k=0;k

{

cin>>i>>j>>w;

while(!check(i,j,w))

{

cout<

cin>>i>>j>>w;

}

matrix[i][j]=w;

}

}

}

}

graph::~graph() //析构函数

{

for(int i=0;i

delete[] matrix[i];

delete[] matrix;

}

//设置指定边权值:

void graph::setEdgeWeight(int beg,int end,int weight)

{

if(isWeighted)

{

while(!check(beg,end,weight))

{

cout<

cin>>beg>>end>>weight;

}

if(isDirected)

matrix[beg][end]=weight;

else

matrix[beg][end]=matrix[end][beg]=weight;

}

else

{

while(!check(beg,end,1))

{

cout<

cin>>beg>>end;

}

if(isDirected) //对邻接矩阵的值进行反转,重置,1变成0,0变成1

matrix[beg][end]=1-matrix[beg][end];

else

matrix[beg][end]=matrix[end][beg]=1-matrix[beg][end];

}

}

//输入检查

bool graph::check(int i,int j,int w)

{

if(i>=0 && i=0 && j0)

return true;

else

return false;

}

void graph::printAdjacentMatrix()

{

cout.setf(ios::left);

cout<

for(int i=0;i

cout<

cout<

for(int i=0;i

{

cout<

for(int j=0;j

cout<

cout<

}

}

longest_path_constitute.h

#include "Graphic_longest_path.h"

#include

#include

#define INFINITY 0x7fffffff

int max(int a,int b)

{

return a>b?a:b;

}

int Find_longest_path(int **weight,int numVertexes,int k,int t,vector &r,int *solution) //寻找k到t的最短路径

{

if(r[k]>=0)

return r[k];

if(k==t)

{

int q=0;

r[k]=q;

solution[k]=t;

return q;

}

else

{

int q=weight[k][t];

if(weight[k][t])

solution[k]=t;

for(int i=k+1;i<=t && weight[k][i];i++)

{

int tmp=max(q,weight[k][i]+Find_longest_path(weight,numVertexes,i,t,r,solution));

if(tmp>q)

{

q=tmp;

solution[k]=i;

}

}

r[k]=q;

return q;

}

}

int dynamic_longest_path(int **weight,int numVertexes,int k,int t,int *solution)

{

vector r;

r.resize(numVertexes);

for(int i=0;i

{

r[i]=-INFINITY;

}

//完成初始化

return Find_longest_path(weight,numVertexes,k,t,r,solution);

}

void print_solution(int *solution,int k,int t)

{

if(solution[k]==-1)

cout<

else

{

cout<

cout< ";

while(k!=t)

{

cout<

if(solution[k]!=t)

{

cout< ";

}

k=solution[k];

}

cout<

}

}

Graphic_longest_path.cpp

#include "longest_path_constitute.h"

#include

int main()

{

cout<

bool isDirected, isWeighted;

int numV;

cout<

cout<

cin>>numV;

cout<

cin>>isWeighted;

cout<

cin>>isDirected;

graph graph(numV,isWeighted,isDirected);

cout<

isDirected ? cout<

isWeighted ? cout<

graph.createGraph();

cout<

graph.printAdjacentMatrix();

cout<

int k,t;

cout<

cin>>k>>t;

int numVertex=graph.getVerNums();

int **weight_dynamic=graph.getWeight();

cout<

cout<

//初始化solution:

int *solution=new int[numVertex+1];

for(int i=0;i

solution[i]=-1;

//返回最优解:

int result=dynamic_longest_path(weight_dynamic,numVertex,k,t,solution);

cout<

cout<

//返回solution的解,注意delete[]

cout<

print_solution(solution,k,t);

int beg, end, weight;

bool flag;

cout<

cin>>flag;

if(flag)

{

if(isWeighted)

{

cout<

cin>>beg>>end>>weight;

graph.setEdgeWeight(beg,end,weight);

}

else

{

cout<

cin>>beg>>end;

graph.setEdgeWeight(beg,end,1);

}

cout<

cout<

graph.printAdjacentMatrix();

}

return 0;

}

输出结果

b8e0c3437ca547f3fb1136b308cb5892.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值