W
H
X

SCOJ4427 / TOPOI 4404: Miss Zhao's Graph 题解

题目链接

SCOJ

TOPOI

题目描述

Problem

给定一个包含n个顶点m条边的带权有向图,找一条边数最多的路径,且路径上的边的权值严格递增。
图中可能有重边和自环。

Input Data

第一行,两个整数nm,表示顶点数和边数。
接下来m行,每行三个整数u,v,w,表示顶点u到顶点v有一条权值为w的边。

Output Data

一行,一个整数。

Input Sample 1

3 3
1 2 1
2 3 2
3 1 3

Output Sample 1

3

 

Input Sample 2   

6 7

1 2 1

3 2 5

2 4 2

2 5 2

2 6 9

5 4 3

4 3 4

Input Sample 2

6

 

Data Limit

 

 

题目思路

由于我太弱了,想不出更好的做法 ,更快更强的做法请看 大佬的题解这个可以点

可能会有长度相同的边而又要满足严格递增是这道题中的问题所在

蒟蒻的思路很简单,用vector存以每一个节点结尾的路径信息 (数组会MLE

信息1:这个点是由哪条边过来的  

信息2:由这条边过来的路径最大长度是多少

 

具体做法

先对每条边按长度排序,保证长度不下降

第一条边单独做,直接将信息存入vector

 

sort (a + 1, a + m + 1, cmp);  //将边按从大到小排序 
v[a[1].v].push_back((q){1, 1});  //第一条边单独处理

 

然后枚举每一条边,枚举每个u的方案,更新方案和答案

 

代码

代码不长,但是挺慢,空间也大,大佬的强多了

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 300008;
int n, m, ans = 1;
struct e{
	int u, v, w;
}a[maxn];  //e记录每一条边信息 
struct q{
	int num, k;   //num表示路径长度(边数),k表示由第k条边走来 
}; //q存储到每个节点方案的信息 
bool cmp (e a, e b) {
	return a.w < b.w;
}
vector <q> v[maxn];
int main(){
	scanf ("%d %d", &n, &m);
	for (int i = 1; i <= m; i++)  scanf ("%d %d %d", &a[i].u, &a[i].v, &a[i].w);
	sort (a + 1, a + m + 1, cmp);  //将边按从大到小排序 
    v[a[1].v].push_back((q){1, 1});  //第一条边单独处理 
	for (int i = 2; i <= m; i++){
		v[a[i].v].push_back((q){1, i});  //先存入vector中 
		int t = a[i].u, len = v[a[i].v].size();  //记录当前的长度(下标) 
		for (int j = 0; j < v[t].size(); j++){   //枚举u的方案 
			if (a[v[t][j].k].w < a[i].w) {      
				v[a[i].v][len-1].num = max (v[a[i].v][len-1].num, v[t][j].num + 1);
				ans = max (ans, v[a[i].v][len-1].num);
				//如果满足严格递增更新方案和答案 
			}
		}
	}
	printf ("%d", ans);
	return 0;
}

 

posted @ 2019-03-24 09:24  -敲键盘的猫-  阅读(231)  评论(2编辑  收藏  举报