工厂的烦恼【SPAF】

Time Limit:10000MS Memory Limit:65536K
Total Submit:130 Accepted:81
Case Time Limit:1000MS


Description
  某工厂发现厂里的机器在生产产品时要消耗大量的原材料,也就是说,有大量的原材料变成了废物。因此厂里想找出消耗原材料最大的一条生产线路进行改造,以降低成本。厂里的生产线路是一个有向无环网络,有 N N 台机器分别代表网络中的 N N 个结点。弧 < I , j > ( i < j ) < I,j >(i < j) 表示原材料从机器i传输到机器j的损耗数量。


Input
第一行是两个整数 N N M M N < = 100 , M < = 1000 (N<=100,M<=1000) ,分别表示网络的结点个数和弧数。第二行至 M + 1 M+1 行,每行三个整数 A A B B C C ,表示弧上的损耗为 C C

Output
仅一个整数,为损耗最大的线路的损耗量。


Sample Input
5 5
1 2 2
2 4 9
1 3 7
3 4 1
4 5 6

Sample Output
17


解题思路

算法详情请见:SPAF.


代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
using namespace std;
const int INF=0X7fffffff;
int h=0,t=1,v[100000],q[100000],n,m,c,dis[100000],head[100000],k,b[100000],maxn,ans=0;
//dis[i]记录从起点s到i的最短路径,v记录一个点是否现在存在在队列中,q是队列
int x,y,z;
struct c{//邻接表记录连接i,j的边,让后面不用枚举所有点
	int x,w,next;
}a[100000]; 
void bfs(int s)
{
	int x;
	memset(v,0,sizeof(v));
	memset(dis,0,sizeof(dis));
	memset(q,0,sizeof(q));
	v[s]=1;
	q[1]=s;
	dis[s]=0;
	h=0;
	t=1;
	do{
		h++;
		x=q[h];//头指针向下移一位,取出指向的点u
		for(int i=head[x];i;i=a[i].next)//注意不要去枚举所有点,用数组模拟邻接表存储
		{
			if(dis[x]+a[i].w>dis[a[i].x])//[松弛操作](https://baike.baidu.com/item/%E6%9D%BE%E5%BC%9B%E6%93%8D%E4%BD%9C/7554089?fr=aladdin).
			{
				dis[a[i].x]=dis[x]+a[i].w;
				if(!v[a[i].x])//队列中不存在v点,v入队
				{
					v[a[i].x]=1;
					t++;
					q[t]=a[i].x;//尾指针下移一位,v入队
				}
			}
		} 
		v[x]=0;
	}while(h<t);
}
void add(int x,int y,int z){
	++k;
	a[k].x=y;
	a[k].w=z;
	a[k].next=head[x];
	head[x]=k;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
	}
	for(int i=1;i<=n;i++)
	{
		maxn=0;
		bfs(i);
		for(int j=1;j<=n;j++)
		if(dis[j]>ans)
			ans=dis[j];
	}
	cout<<ans;
}
发布了73 篇原创文章 · 获赞 5 · 访问量 1835

猜你喜欢

转载自blog.csdn.net/kejin2019/article/details/103998634