23132 Problem A 关键路径

本文介绍了一种求解关键路径的经典算法,并通过实例演示了如何利用邻接矩阵来确定图中的关键路径及其长度。该算法适用于从源点到汇点的所有路径中寻找最长路径的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题 A: 关键路径

时间限制: 1 Sec  内存限制: 128 MB
提交: 43  解决: 15

 

题目描述

描述:

图的连接边上的数据表示其权值,带权值的图称作网。
上图可描述为顶点集为(a,b,c,d,e)
边集及其权值为(始点,终点 权值):
 a b 3
 a c 2 
 b d 5
 c d 7 
 c e 4
 d e 6            

 

  网的源点是入度为0的顶点,汇点是出度为0的顶点。网的关键路径是指从源点到汇点的所有路径中,具有最大路径长度的路径。上图中的关键路径为a->c->d->e,其权值之和为关键路径的长度为15。

  本题的要求是根据给出的网的邻接矩阵求该网的关键路径及其长度。

 

输入

第一行输入一个正整数n(1<=n<=5),其代表测试数据数目,即图的数目

第二行输入x(1<=x<=15)代表顶点个数,y(1<=y<=19)代表边的条数

第三行给出图中的顶点集,共x个小写字母表示顶点

接下来每行给出一条边的始点和终点及其权值,用空格相隔,每行代表一条边。

输出

第一个输出是图的关键路径(用给出的字母表示顶点, 用括号将边括起来,顶点逗号相隔)

第二个输出是关键路径的长度

每个矩阵对应上面两个输出,两个输出在同一行用空格间隔,每个矩阵的输出占一行。

 

样例输入

2
5 6
abcde
a b 3
a c 2
b d 5
c d 7
c e 4
d e 6
4 5
abcd
a b 2
a c 3
a d 4
b d 1
c d 3

样例输出

(a,c) (c,d) (d,e) 15
(a,c) (c,d) 6

提示

作者:梁青青

经验总结

这一题也是经典的求关键路径问题,需要注意的是,在e[ i ]==l[ i ]时,将边存储起来,最后找到源点进行输出,否则输出的路径顺序会不符合要求,其他的就没啥啦~  睡觉睡觉~(:3[▓▓]

正确代码

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <algorithm>
using namespace std;

const int maxn=20;
int inDegree[maxn];
struct node
{
	int v,w;
	node(int a,int b):v(a),w(b){};
};
vector<node> adj[maxn];
vector<int> ans[maxn];
stack<int> topoSeq;
int n,m,ve[maxn],vl[maxn];
char str[maxn];
map<char,int> mp;
bool topologicalSort()
{
	memset(ve,0,sizeof(ve));
	queue<int> q;
	for(int i=0;i<n;++i)
	{
		if(inDegree[i]==0)
		{
			q.push(i);
		}
	}
	while(q.size())
	{
		int u=q.front();
		topoSeq.push(u);
		q.pop();
		for(int i=0;i<adj[u].size();++i)
		{
			int v=adj[u][i].v;
			int w=adj[u][i].w;
			--inDegree[v];
			if(inDegree[v]==0)
				q.push(v);
			if(ve[u]+w>ve[v])
				ve[v]=ve[u]+w;
		}
	}
	if(topoSeq.size()==n)
		return true;
	else
		return false;
}
int criticalPath()
{
	if(topologicalSort()==false)
		return -1;
	int maxlength=0;
	for(int i=0;i<n;++i)
	{
		if(ve[i]>maxlength)
			maxlength=ve[i];
	}
	fill(vl,vl+maxn,maxlength);
	while(topoSeq.size())
	{
		int u=topoSeq.top();
		topoSeq.pop();
		for(int i=0;i<adj[u].size();++i)
		{
			int v=adj[u][i].v;
			int w=adj[u][i].w;
			if(vl[v]-w<vl[u])
				vl[u]=vl[v]-w;
		}
	}
	for(int i=0;i<n;++i)
		ans[i].clear();
	for(int u=0;u<n;++u)
	{
		for(int i=0;i<adj[u].size();++i)
		{
			int v=adj[u][i].v;
			int w=adj[u][i].w;
			int e=ve[u];
			int l=vl[v]-w;
			if(e==l)
			{
				ans[u].push_back(v);
			}
		}
	}
	int s;
	for(int i=0;i<n;++i)
	{
		if(ve[i]==0)
		{
			s=i;
			break;
		}
	}
	while(ans[s].size())
	{
		printf("(%c,%c) ",str[s],str[ans[s][0]]);
		s=ans[s][0];
	}
	return maxlength;
}
int main()
{
	int n1,w;
	char a,b;
	while(~scanf("%d",&n1))
	{
		for(int i=0;i<n1;++i)
		{
			for(int j=0;j<n;++j)
				adj[j].clear();
			memset(inDegree,0,sizeof(inDegree));
			scanf("%d %d",&n,&m);
			scanf("%s",str);
			mp.clear();
			for(int j=0;j<n;++j)
			{
				mp[str[j]]=j;
			}
			for(int j=0;j<m;++j)
			{
				getchar();
				scanf("%c %c %d",&a,&b,&w);
				adj[mp[a]].push_back(node(mp[b],w));
				++inDegree[mp[b]];
			}
			int length=criticalPath();
			printf("%d\n",length);
		}
	}
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值