2021-02-15

算法整理:拓扑排序(1)

落谷:杂货1113


问题简述:

每一个节点有一个代价值cost[i],在有向无环图中寻找一个拓扑序最小的序列,并求出最小的拓扑序列和


算法分析:

提示:在拓扑序模板的基础上加入动态规划。

详见题解


代码及注释:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <stack>
using namespace std;
#pragma warning(disable:4996)

int find(vector<int>& v, int e)
{
    
    
	for (int i = 0; i<int(v.size()); ++i)
		if (e == v[i])
			return i+1;
	return -1;
}

int main()
{
    
    
	//freopen("data.txt","r", stdin);
	int n;
	cin >> n;
	vector<vector<int>> v(n+1);  //保存每一项工作的准备工作的编号
	vector<int> cost(n+1);   //保存输入的每一项工作的耗时
	vector<int> ans;     //ans[i]表示做完第i项工作及其准备工作后的耗时
	vector<int> count;   //保存每一项工作前驱工作的数量
	ans.resize(n+1, 0); 
	count.resize(n+1, 0);
	stack<int> s;//保存当前可以执行的工作的编号
	//处理输入
	for (int i = 1; i <= n; ++i)
	{
    
    
		int temp;
		cin >> temp;
		cin >> temp;
		cost[i]=(temp); //将每一项工作的耗时都加入数组
		while (true)  //保存每一项工作的先前工作
		{
    
    
			cin >> temp;
			if (temp == 0)
				break;   //为0表示结束了
			else
			{
    
    
				v[i].push_back(temp);
				count[i]++;
			}
		}
	}

	//拓扑序列模板
	//先初始化栈,将不需要准备的工作先加入栈
	for (int i = 1; i <= n ; ++i)
		if (count[i] == 0)
		{
    
    
			s.push(i);
			ans[i] = cost[i];
		}
	//依次从栈顶中取出元素,每取出一个元素后考虑该元素的贡献,即该元素是哪些工作的准备工作
	while (!s.empty())
	{
    
    
		int temp = s.top();
		s.pop();
		for (int i = 1; i<= n ; ++i)
		{
    
    
			int index = find(v[i], temp);
			if (index!= -1)
			{
    
    
				ans[i] = max(ans[i], cost[i] + ans[temp]);   
				if ((--count[i]) == 0)
					s.push(i);
			}
		}	
	}
	//截止每一项工作的最大耗时就是所需的答案
	int max_ans = ans[1];
	for (int i = 1; i <= n; ++i)
		max_ans = max(max_ans, ans[i]);
	cout << max_ans << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sddxszl/article/details/113817013