每日一练——最长路(图论)

​​​​​​P1807 最长路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题可以用迪杰斯特拉、bellford、floyd、toposort、bfs(后两个本质上是一样的)。下面我将给出后三者的代码。

//floyd(392ms)做了许多无用功
#include <bits/stdc++.h>
#define MOD 1000000007
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int n,m;
int f[1600][1600];
int main() {
	cin>>n>>m;
    //初始化
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++) {
			if(i==j) f[i][j]=0;
			else f[i][j]=-INF;
		}
    //输入u到v权值为w
	while(m--) {
		int u,v,w;
		cin>>u>>v>>w;
		f[u][v]=max(f[u][v],w);//多条边
	}
    //floyd
	for(int k=1; k<=n; k++)
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++)
				if(f[i][k]!=-INF && f[k][j]!=-INF)//没有这句的话会wa一个点
					f[i][j]=max(f[i][j],f[i][k]+f[k][j]);
	if(f[1][n]==-INF) cout<<-1;//没连通路
	else cout<<f[1][n];
	return 0;
}

 

//toposort(51ms)
#include <bits/stdc++.h>
#define MOD 1000000007
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int n,m;
int ind[1600],maxn[1600],vis[1600];//入度,距离,标记 
//结构体用于将当前起点可以走到的终点和其权值捆绑在一起 
struct node {
	int from,to,w;
};
vector<node> G[1600];//当前起点所指向的所有终点都与其起点有关 
queue<int> q;

void toposort() {
	for(int i=1; i<=n; i++)
	if(ind[i]==0) q.push(i);
	while(!q.empty()) {
		int h=q.front();
		q.pop();
		for(int i=0; i<G[h].size(); i++) {
			node j=G[h][i];
			//终点的入度值--(topo的规矩) 
			ind[j.to]--;
			if(ind[j.to]==0) q.push(j.to);//入度为0后也算是一个起点了 
			//起点到该终点已经有路 
			if(vis[h]) {
				//原本已经有一条路了,不过要求最长路,所以更新一下。 
				if(maxn[j.to]<maxn[h]+j.w) maxn[j.to]=maxn[h]+j.w;
				vis[j.to]=1;//标记一下终点 
			}
		}
	}
}

int main() {
	cin>>n>>m;
	for(int i=1; i<=m; i++) {
		node now;
		cin>>now.from>>now.to>>now.w;
		ind[now.to]++;//入度 
		G[now.from].push_back(now); 
	}
	maxn[n]=-1,vis[1]=1;//初始化到n点为-1 
	toposort();
	cout<<maxn[n];//从1到达n的距离 
	return 0;
}
//BFS
#include <bits/stdc++.h>
#define MOD 1000000007
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int n,m;
int f[1600][1600],d[1600];//从u到v的最长路    从1到i的最长路
queue<int> q;

void bfs() {
	q.push(1);//起点
	d[1]=0;//初始化
	while(!q.empty()) {
		int h=q.front();
		q.pop();
		for(int i=1; i<=n; i++) {
            //非0且距离较小便可更新
			if(f[h][i] && d[i]<d[h]+f[h][i]) {
				d[i]=d[h]+f[h][i];
				q.push(i);//更新后的终点需要入队,用于后续继续BFS来增加长度
			}
		}
	}
}


int main() {
	cin>>n>>m;
	memset(d,-1,sizeof(d));//便于输出
	for(int i=1; i<=m; i++) {
		int u,v,w;
		cin>>u>>v>>w;
		f[u][v]=max(f[u][v],w);//两点间的最长路
	}
	bfs();
	cout<<d[n];
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_谦言万语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值