https://vjudge.net/problem/1476682/origin
这个东西是给个图,每条边带有一个id(id各不相等),每个边带有一个权值,求最长路径,路径上的权值递增,id递增
嗯~~刚开始不知道咋做,权值+id 好像也不太好dp
后来知道,要动态处理,例如把边按从大到小处理,
那么利用dp[i]表示从i开始的最长路径的长,注意,由于id是从大到小的
所以每取一条边{from,to,v,id},能够更新的只有dp[from]这样更新的复杂度就可以降到最低,
代码:
//Problem:
//Date:
//Skill:
//Bug:
/Definations/
//循环控制
#define CLR(a) memset((a),0,sizeof(a))
#define F(i,a,b) for(int i=a;i<=int(b);++i)
#define F2(i,a,b) for(int i=a;i>=int(b);--i)
#define RE(i,n) for(int i=0;i<int(n);i++)
#define RE2(i,n) for(int i=1;i<=int(n);i++)
//输入输出
//#define INC(c) do{scanf("%c",&c);}while(isspace(c))
//#define ON cout<<endl
#define PII pair<int,int>
using namespace std;
const int inf = 0x3f3f3f3f;
const long long llinf = 0x3f3f3f3f3f3f3f3f;
Options//
typedef long long ll;
#define stdcpph
#define CPP_IO
#ifdef stdcpph
#include<bits/stdc++.h>
#else
#include<ctype.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<algorithm>
#include<functional>
#ifdef CPP_IO
#include<iostream>
#include<iomanip>
#include<string>
#else
#include<stdio.h>
#endif
#endif
Basic Functions//
template<typename INint>
inline void IN(INint &x)
{
x = 0; int f = 1; char c; cin.get(c);
while (c<'0' || c>'9') { if (c == '-')f = -1; cin.get(c); }
while (c >= '0'&&c <= '9') { x = x * 10 + c - '0'; cin.get(c); }
x *= f;
}
template<typename INint>
inline void OUT(INint x)
{
if (x > 9)OUT(x / 10);
cout.put(x % 10 + '0');
}
Added Functions//
const int maxn = int(1e5+4);
struct Edge
{
int v;
int id, w;
bool operator<(const Edge b)const
{
//return id < b.id&&w < b.w;
return id < b.id;
}
};
set<Edge>G[maxn];
vector<int>es;
map<int,int> dp[maxn];//从i号结点开始,第一条边长为j的最长长度
int get( int v, int w)//从v开始 ,第一条边长>w的 路径长度
{
int ret;
auto it = dp[v].upper_bound( w);//获取大于w的边
if (it == dp[v].end())ret = 0;
else ret = it->second;
return ret ;
}
Code/
int main()
{
//freopen("C:\\Users\\VULCAN\\Desktop\\data.in", "r", stdin);
int T(1), times(0);
#ifdef CPP_IO// CPP_IO
std::ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
//cin >> T;
#else
//IN(T);
#endif
/
while (++times, T--)
{
//memset(dp, -1, sizeof(dp));
int n, m; cin >> n >> m;
RE2(i, m)
{
int u, v, w;
IN(u); IN(v); IN(w);
es.push_back(u); es.push_back(v); es.push_back(w);
//G[u].push_back({ v,i,w });
}
ll ans(0);
for(int i=m;i>=1;i--)
{
int u, v, w;
w = es[i * 3 - 1]; v = es[i * 3 - 2]; u = es[i * 3 - 3];
int id = i;
//G[u].insert({ v,id,w });
int bui = get(v, w)+1;//从v开始的,第一边为w的,最长路径长
int ori = get(u, w - 1);//从u开始的>=w的最佳长度
if (bui<=ori)
continue;
else
{
dp[u][w] = bui;
auto it = dp[u].lower_bound(w);//从u开始的,第一边长>w的
while (it!=dp[u].begin())//没有边或者,路径长大于
{
--it;
if (it->second > bui)
continue;
else
it= dp[u].erase(it);
}
}
ans = max(ans, (ll)bui);
}
cout << ans << endl;
}
///
return 0;
}