1. 程式人生 > >SCOJ4427 / TOPOI 4404: Miss Zhao's Graph 題解

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

處理 logs its boa max 最大 長度 bool rap

題目鏈接

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;
}

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