1. 程式人生 > >[C++ map & dp]codeforces 960F. Pathwalks

[C++ map & dp]codeforces 960F. Pathwalks

pat fin 維護 sin view 刪除 define def close

題目傳送門:960F

思路:

題目給人的感覺很像最長上升子序列,自然而然想到用dp的思路去處理

題目中給的限制條件是,要接上前面的邊,前面的邊權一定要小於當前的邊權(題目按照輸入的順序,因此只找前面的邊)

對於每個結點,我們要維護的信息是:

  當前狀態下,w的邊權到達這個點,最多能有幾條邊

如何維護這個信息呢?如果對每個點開一個maxn的數組,每次暴力修改,顯然是過不去的

一種處理辦法是:對每個點建動態線段樹(可是本菜雞不會!!。。我馬上去學

另一種簡單的處理辦法:用map以及map內置的函數

對每個點建立一個map<int,int> 保存對應邊權下,能達到的最大的邊數

vector< map<int,int> > s;
...
s.resize(n+1);

對於每條邊(a,b,w), 查a點的map裏,小於w 的最大的邊數

1 int get_edge_no(int a,int w){
2     auto t = s[a].lower_bound(w);
3     if(t == s[a].begin())return 0;
4     --t;
5     return t->second;
6 }

然後得到b對應的w的結果,再保存至b的map裏

1         int
t = get_edge_no(a,w) + 1; 2 if(t < get_edge_no(b,w+1))continue; 3 s[b][w] = t;

保存之後,一定要將map裏w大 val小的元素刪除(因為這部分數據也需要更新)

1         auto it = s[b].upper_bound(w);
2         while(it != s[b].end() && it->second < t){
3             it = s[b].erase(it);
4         }
5 ans = max(ans,t);

完整代碼:

技術分享圖片
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 #define _____ ios::sync_with_stdio(false);cin.tie(0);
 5 int n,m;
 6 const int maxn = 100005;
 7 vector< map<int,int> > s;
 8 int get_edge_no(int a,int w){
 9     auto t = s[a].lower_bound(w);
10     if(t == s[a].begin())return 0;
11     --t;
12     return t->second;
13 }
14 int main(){
15     //freopen("data.in","r",stdin);
16     _____
17     cin >> n >> m;
18     s.resize(n+1);
19     int a,b,w;
20     int ans = 0;
21     for(int i = 1; i <= m; i++){
22         cin >> a >> b >> w;
23         int t = get_edge_no(a,w) + 1;
24         if(t < get_edge_no(b,w+1))continue;
25         s[b][w] = t;
26         auto it = s[b].upper_bound(w);
27         while(it != s[b].end() && it->second < t){
28             it = s[b].erase(it);
29         }
30         ans = max(ans,t);
31     }
32     cout << ans << \n;
33     return 0;
34 }
View Code

下面整理一下map裏好用的內置函數:

添加元素:

map<typename,typename>.insert( pair<typename,typename> ); // 註意參數是pair類型 返回一個pair類型,first成員是一個叠代器,second成員是一個bool值,true:插入成功 false:已存在 刪除元素: map.erase( k ); 刪除關鍵字為k的元素,返回刪除的元素數量 map.erase( p );
刪除叠代器p指定的元素,返回指向p之後的元素 map.erase(b,e); 刪除叠代器對b,e之間的元素,返回e 查找元素: map.upper_bound( k ); map.lower_bound( k ); 以第一關鍵字比較大小,返回一個叠代器 map.equal_range(k); 返回一個叠代器pair,表示關鍵字等於k的範圍。若不存在,都等於map.end()

[C++ map & dp]codeforces 960F. Pathwalks