题解
- 这题一开始以为可以用dijkstra求解,但是实际上不行。原因在于最短路径问题中有最优子结构,即最短路径的子路径还是最短路径,dijkstra就是利用了这一点,而最长路径问题中没有该子结构。
- 实际上求最长路径是NP-hard问题,但是其有线性时间的解。对于有向无环图而言,先拓扑排序,再动态规划求解即可。这里和dijkstra一样是以最长求最长的思想,但是这里不像求最短一样能直接得到源点到某个点的最长距离,而如果拓扑有序后,就可以先取序列中靠前的点求最长,然后动态规划逐步求靠后点的最长距离。
- 求最长路径也就是求关键路径。
题目
问题 E: 有向无环图上的最长路径(DS图)
时间限制: 1 Sec 内存限制: 128 MB
提交: 3 解决: 2
[提交][状态][讨论版]
题目描述
求出下面有向图中,顶点“5”到其他所有顶点的最长路径和长度。
输入
根据上面的有向图结构,在内存中用邻接表(Adjacency List)存储该图。
第1行:顶点数
第2行:边数
第3行:一条有向边
第4行:一条有向边
……
输出
第1行:从5到0的最长路径,路径长度
第2行:从5到1的最长路径,路径长度
第3行:从5到2的最长路径,路径长度
第4行:从5到3的最长路径,路径长度
……
样例输入
8
13
5 4 0.35
4 7 0.37
5 7 0.28
5 1 0.32
4 0 0.38
0 2 0.26
3 7 0.39
1 3 0.29
7 2 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93
样例输出
5 1 3 6 4 0
5 1
5 1 3 6 4 7 2
5 1 3
5 1 3 6 4
5 1 3 6
5 1 3 6 4 7
代码(dijkstra)(WA)
#include <iostream>
using namespace std;
class ListNode
{
int vertex;
double weight;
ListNode *next;
public:
ListNode(){next = NULL;}
friend class Graph;
};
class Graph
{
private:
int vexnum;
int edgenum;
ListNode **adjlist;
int *s;
double *dist;
int *path;
int IsOver();
void DisplayPath(int i);
public:
Graph();
~Graph();
void Dijkstra(int vex);
};
Graph::Graph()
{
int i;
cin>>vexnum>>edgenum;
adjlist = new ListNode*[vexnum];
s = new int[vexnum];
dist = new double[vexnum];
path = new int[vexnum];
for(i=0; i<vexnum; i++)
{
s[i] = 0;
dist[i] = 0;
path[i] = -1;
adjlist[i] = new ListNode;
}
for(i=0; i<edgenum; i++)
{
ListNode *p;
int startvex, endvex;
double weight;
cin>>startvex>>endvex>>weight;
p = new ListNode;
p->weight = weight;
p->vertex = endvex;
p->next = adjlist[startvex]->next;
adjlist[startvex]->next = p;
}
}
Graph::~Graph()
{
delete []adjlist;
delete []s;
delete []dist;
delete []path;
}
int Graph::IsOver()
{
for(int i=0; i<vexnum; i++)
{
if(!s[i])
return 0;
}
return 1;
}
void Graph::Dijkstra(int vex)
{
ListNode *p;
p = adjlist[vex];
while(p->next)
{
p = p->next;
dist[p->vertex] = p->weight;
path[p->vertex] = vex;
}
s[vex] = 1;
while(!IsOver())
{
int temp;
double maxweight = 0;
for(int i=0; i<vexnum; i++)
if(dist[i]>maxweight && !s[i])
{
maxweight = dist[i];
temp = i;
}
s[temp] = 1;
p = adjlist[temp];
while(p->next)
{
p = p->next;
if(dist[temp]+p->weight>dist[p->vertex] && !s[p->vertex])
{
dist[p->vertex] = dist[temp]+p->weight;
path[p->vertex] = temp;
}
}
}
for(int i=0; i<vexnum; i++)
{
cout<<dist[i]<<' '<<path[i]<<endl;
}
}
int main(void)
{
Graph myGraph;
myGraph.Dijkstra(5);
}
代码(拓扑+动态规划)(AC)
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
class ListNode
{
int vertex;
double weight;
ListNode *next;
public:
ListNode(){next = NULL;}
friend class Graph;
};
class Graph
{
private:
int vexnum;
int edgenum;
ListNode **adjlist;
double **matrix;
int *S;
int *s;
double *dist;
int *path;
int IsOver();
void DisplayPath(int i);
void TopologicalSort();
public:
Graph();
~Graph();
void Dijkstra();
};
Graph::Graph()
{
int i, j;
cin>>vexnum>>edgenum;
adjlist = new ListNode*[vexnum];
s = new int[vexnum];
S = new int[vexnum];
dist = new double[vexnum];
path = new int[vexnum];
matrix = new double*[vexnum];
for(i=0; i<vexnum; i++)
{
s[i] = 0;
dist[i] = 0;
path[i] = -1;
adjlist[i] = new ListNode;
matrix[i] = new double[vexnum];
for(j=0; j<vexnum; j++)
matrix[i][j] = 0;
}
for(i=0; i<edgenum; i++)
{
ListNode *p;
int startvex, endvex;
double weight;
cin>>startvex>>endvex>>weight;
p = new ListNode;
p->weight = weight;
p->vertex = endvex;
p->next = adjlist[startvex]->next;
adjlist[startvex]->next = p;
matrix[startvex][endvex] = weight;
}
}
Graph::~Graph()
{
delete []adjlist;
delete []s;
delete []dist;
delete []path;
for(int i=0; i<vexnum; i++)
delete []matrix[i];
delete []matrix;
}
int Graph::IsOver()
{
for(int i=0; i<vexnum; i++)
{
if(!s[i])
return 0;
}
return 1;
}
void Graph::DisplayPath(int i)
{
stack<int> s;
s.push(i);
while(path[i]!=-1)
{
i = path[i];
s.push(i);
}
while(!s.empty())
{
i = s.top();
s.pop();
cout<<i<<' ';
}
cout<<endl;
}
void Graph::TopologicalSort()
{
int num = 0;
while(!IsOver())
{
int i, j;
for(i=0; i<vexnum; i++)
{
if(!s[i])
{
for(j=0; j<vexnum; j++)
{
if(matrix[j][i])
break;
}
if(j==vexnum)
break;
}
}
s[i] = 1;
S[num] = i;
num++;
for(j=0; j<vexnum; j++)
matrix[i][j] = 0;
}
}
void Graph::Dijkstra()
{
TopologicalSort();
int i;
ListNode *q;
for(i=0; i<vexnum; i++)
{
int temp = S[i];
q = adjlist[temp];
while(q->next)
{
q = q->next;
if(dist[q->vertex]<dist[temp]+q->weight)
{
dist[q->vertex] = dist[temp]+q->weight;
path[q->vertex] = temp;
}
}
}
for(i=0; i<vexnum; i++)
{
if(i!=S[0])
DisplayPath(i);
}
}
int main(void)
{
Graph myGraph;
myGraph.Dijkstra();
}