PAT (MOOC) 06-5. 关键活动 (30)

37 篇文章 0 订阅
#include<vector>
#include<cstring>
#include<fstream>
#include<algorithm>
#include<map>
#include<iostream>
using namespace std;
//ifstream fin("06-4.txt");
//#define cin fin
#define MAX 101
typedef struct eg *ed;
typedef struct ee *e;
struct ee{
	int s, d;
	ee(int s, int d){
		this->s = s;
		this->d = d;
	}
};
struct eg{
	int weight;
}edge[MAX][MAX];
int n, m;
int start, end1;
bool vst[MAX];//此题是因为要判定环路 才设定vst数组的 否则是不用的
vector<e> path_e, max_path_e;
map<int, int> prio;
int path = 0, max_path = -1;
bool isru_zero(int v){
	for (int i = 1; i <= n; i++)
	if (edge[i][v].weight >= 0)	return false;
	return true;
}
bool dfs(int v){
	if (path > max_path){
		end1 = v;
		max_path = path;
	}
	for (int i = 1; i <= n; i++){
		if (edge[v][i].weight > 0){
			if (vst[i]){
				return false;
			}
			path += edge[v][i].weight;
			vst[i] = true;
			if (!dfs(i))	return false;
			path -= edge[v][i].weight;
			vst[i] = false;
		}
	}
	return true;
}
bool find(e p, vector<e> path, int size){
	for (int i = 0; i<size;i++)
	if (path[i]->s == p->s&&path[i]->d == p->d)
		return true;
	return false;
}
void dfs_re1(int v){
	if (isru_zero(v)){
		if (path >= max_path){
//			end1 = v;
			max_path = path;
			int size = path_e.size();
			max_path_e.resize(size);
			for (int i = 0; i < size; i++)
				max_path_e[i] = path_e[i];
		}
	}
	for (int i = 1; i <= n; i++){
		if (edge[i][v].weight > 0){
			path += edge[i][v].weight;
			e eg = new ee(i, v);
			path_e.push_back(eg);
			dfs_re1(i);
			path_e.pop_back();
			path -= edge[i][v].weight;
		}
	}
}
void dfs_re2(int v){
	if (isru_zero(v) && path == max_path){
		int max_size = max_path_e.size(), size = path_e.size();
		for (int i = 0; i<size; i++)
		if (!find(path_e[i], max_path_e, max_size)){
			max_path_e.push_back(path_e[i]);
//			max_size++;//没必要此时知道max_path_e的大小,查找时也不用找最后新加进的这些,最后输出再算总的即可
		}
	}
	for (int i = 1; i <= n; i++){
		if (edge[i][v].weight > 0){
			path += edge[i][v].weight;
			e eg = new ee(i, v);
			path_e.push_back(eg);
			dfs_re2(i);
			path_e.pop_back();
			path -= edge[i][v].weight;
		}
	}

}
bool cmp(const e &a,const e &b){
	if (a->s != b->s)
		return (a->s < b->s);
	else{
		int s1 = a->s, d1 = a->d, s2 = b->s, d2 = b->d;
		return (prio[s1*MAX + d1] > prio[s2*MAX + d2]);
	}
}
int main(){
	cin >> n >> m;
	memset(edge, -1, sizeof(edge));
	int c1, c2, w;
	for (int i = 1; i <= m; i++){
		cin >> c1 >> c2 >> w;
		edge[c1][c2].weight = w;
		prio[c1*MAX + c2] = i;
	}
	for (start = 1; start <= n; start++){
		if (isru_zero(start))	break;
	}
	if (start == n + 1){
		printf("0\n"); return 0;
	}
	/*
	从这个入度为0的点开始沿正向深度遍历,找到那最远的点
	*/
	vst[start] = true;
	if (!dfs(start)){
		printf("0\n"); return 0;
	}
	vst[start] = false;
	start = end1;/* 再从最远点逆序遍历 找最远点- - 只要求得max_path值即可 */
	dfs_re1(start);
	printf("%d\n", max_path);
	path_e.clear();
	dfs_re2(start);
	sort(max_path_e.begin(), max_path_e.end(), cmp);
	int size = max_path_e.size();
	for (int i = 0; i < size; i++){
		printf("%d->%d\n", max_path_e[i]->s, max_path_e[i]->d);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值