日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构之基环树——骑士,Island,旅行加强版,Number of Simple Paths,Traffic Network in Numazu,Card Game

發布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构之基环树——骑士,Island,旅行加强版,Number of Simple Paths,Traffic Network in Numazu,Card Game 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • [ZJOI2008]騎士
  • [IOI2008] Island
  • [NOIP2018 提高組] 旅行 加強版
  • CF1454E Number of Simple Paths
  • Traffic Network in Numazu
  • Card Game

基環樹的常見解法

  • 若干個基環樹互相獨立
  • 斷環為鏈(隨便斷一條)
  • 環外樹和環外樹之間的樹形DP
  • 環變鏈后整體可以用數據結構簡單維護操作

[ZJOI2008]騎士

luogu2607

每個人都有討厭的人,將這個條件轉換成兩人之間存在一條邊

原圖則轉換成了若干個互不干擾的基環樹

單獨考慮一棵基環樹

對于“樹”的部分,可以樹形DPDPDP

對于“環”的部分,不用單調隊列,直接隨便找一條環上邊,強制斷開

基環樹就徹底變成了一棵樹

設計dpu,0/1dp_{u,0/1}dpu,0/1?轉移

  • 父親選,則所有兒子不能選
  • 父親不選,則兒子可選可不選
  • 兒子之間也是互相獨立的

分別以斷開的邊的兩端作為樹根,最后就是max(dp[S][0], dp[T][0])

為什么沒有dp[S][1],dp[T][1]?

  • 以S為例,dp[S][0]是S為樹根時強制不選的最大值
  • 此時TTT是樹中一個節點,會根據轉移方程式決定T是否選擇
  • 如果dp[S][0]是不含TTT的,說明最佳方案本來就是S,T都不選擇
  • 所以就不能出現dp[S][1],最佳方案可能包含了T
  • dp[T][0]同理
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define int long long #define maxn 1000005 int n, cnt, S, T, ID; int w[maxn], head[maxn], to[maxn << 1], nxt[maxn << 1]; int dp[maxn][2]; bool vis[maxn];void addedge( int u, int v ) {to[cnt] = v, nxt[cnt] = head[u], head[u] = cnt ++;to[cnt] = u, nxt[cnt] = head[v], head[v] = cnt ++; }void dfs1( int u, int id ) {vis[u] = 1;for( int i = head[u];~ i;i = nxt[i] ) {if( i == id ) continue;int v = to[i];if( vis[v] ) {S = u, T = v, ID = i;continue;}else dfs1( v, i ^ 1 );} }void dfs2( int u, int id ) {dp[u][0] = 0, dp[u][1] = w[u];for( int i = head[u];~ i;i = nxt[i] ) {if( i == id or i == ID or i == ( ID ^ 1 ) ) continue;int v = to[i];dfs2( v, i ^ 1 );dp[u][0] += max( dp[v][0], dp[v][1] );dp[u][1] += dp[v][0];} }signed main() {memset( head, -1, sizeof( head ) );scanf( "%lld", &n );for( int i = 1, x;i <= n;i ++ ) {scanf( "%lld %lld", &w[i], &x );addedge( i, x );}int ans = 0;for( int i = 1;i <= n;i ++ ) {if( vis[i] ) continue;dfs1( i, -1 );int t = 0;dfs2( S, -1 ); t = max( t, dp[S][0] );dfs2( T, -1 ); t = max( t, dp[T][0] );ans += t;}printf( "%lld\n", ans );return 0; }

[IOI2008] Island

luogu4381

同樣的,這是相互獨立的若干棵基環樹

問題轉化為求若干個基環樹的直徑之和

單獨考慮一個基環樹,設計狀態轉移方程

邊權變成入點的點權

fi:if_i:ifi?:i子樹內以iii為鏈端的最長鏈長度

gi:ig_i:igi?:i子樹內的直徑

首先可以利用拓撲做有向圖,求出所有的環,順便轉移出每個點的信息

  • v∈sonuv\in son_uvsonu?
  • 直徑是vvv子樹內的直徑
    • gu=max?(gu,gv)g_u=\max(g_u,g_v)gu?=max(gu?,gv?)
  • 直徑是由uuu的兩條鏈拼接而成,其中一條鏈過vvv
    • gu=max?(fu+fv+wu,v,gu)g_u=\max(f_u+f_v+w_{u,v},g_u)gu?=max(fu?+fv?+wu,v?,gu?)
  • 最長鏈為vvv這一條鏈
    • fu=max?(fu,fv+wu,v)f_u=\max(f_u,f_v+w_{u,v})fu?=max(fu?,fv?+wu,v?)

考慮環上的點信息更新

  • 基環樹直徑可能是某個點的環外子樹直徑
  • 基環樹直徑可能是兩個環點的最長鏈拼接,再加上環上距離

同樣的,枚舉環上某一條邊,強制斷邊,變成一條單鏈后

可以用前綴和差分求環上兩點的距離,距離有兩種

  • 恰好順著斷邊的順序
    • sumj?sumisum_j-sum_isumj??sumi?
  • 反著走環
    • len?(sumj?sumi)len-(sum_j-sum_i)len?(sumj??sumi?)

則環上點拼接成直徑的轉移為

max?(fi+fj+sumj?sumi,fi+fj+len?sumj+sumi)\max(f_i+f_j+sum_j-sum_i,f_i+f_j+len-sum_j+sum_i)max(fi?+fj?+sumj??sumi?,fi?+fj?+len?sumj?+sumi?)

發現i,ji,ji,j之間是獨立的,枚舉到jjj時,記錄前面最大貢獻的iii

Max1=max?{fi?sumi};Max2=max?{fi+sumi}Max_1=\max\{f_i-sum_i\};Max_2=\max\{f_i+sum_i\}Max1?=max{fi??sumi?};Max2?=max{fi?+sumi?}

max?(fj+sumj+Max1,fj+len?sumj+Max2)\max(f_j+sum_j+Max_1,f_j+len-sum_j+Max_2)max(fj?+sumj?+Max1?,fj?+len?sumj?+Max2?)

但是只有當環跑完后我們才知道環長lenlenlen

所以可以把lenlenlen提出去,最后加上再選較大值

#include <queue> #include <cstdio> #include <iostream> using namespace std; #define int long long #define maxn 1000005 queue < int > q; int to[maxn], d[maxn], w[maxn], f[maxn], g[maxn]; bool vis[maxn]; int n;int dfs( int now ) {int x = to[now], sum = w[now];int ans1 = g[now], Max1 = f[now];int ans2 = - 1e18, Max2 = f[now];while( x ^ now ) {d[x] = 0;ans1 = max( ans1, g[x] );ans1 = max( ans1, f[x] + sum + Max1 );ans2 = max( ans2, f[x] - sum + Max2 );Max1 = max( Max1, f[x] - sum );Max2 = max( Max2, f[x] + sum );sum += w[x];x = to[x];}return max( ans1, ans2 + sum ); }signed main() {scanf( "%lld", &n ); for( int i = 1;i <= n;i ++ )scanf( "%lld %lld", &to[i], &w[i] ), d[to[i]] ++;for( int i = 1;i <= n;i ++ )if( ! d[i] ) q.push( i );while( ! q.empty() ) {int u = q.front(); q.pop();int v = to[u];g[v] = max( g[v], max( g[u], f[v] + f[u] + w[u] ) );f[v] = max( f[v], f[u] + w[u] );d[v] --;if( ! d[v] ) q.push( v );}int ret = 0;for( int i = 1;i <= n;i ++ ) if( d[i] ) ret += dfs( i );printf( "%lld\n", ret );return 0; }

[NOIP2018 提高組] 旅行 加強版

luogu5049

  • m=n-1
    • 就是單純的一棵樹,直接dfs搜就可以了
  • m=n
    • 基環樹

一個點只能訪問未訪問點,或者選擇回溯

考慮對于基環樹環上點的幾種選擇

  • case1

對于節點3,肯定是由2過來的,最佳選擇是先遍歷完非環的樹的點5,6,再走環

是不會選擇回溯到2的

  • case2

3的環邊5是其所有邊中最小的,優選走環,后遍歷非環樹,不選擇回溯

  • case3

3的環邊6不是最大也不是最小,選擇先遍歷5再走環邊,最后遍歷8,同樣不會選擇回溯

發現只有當環邊是最大邊的時候就會選擇遍歷完非環樹后回溯

但真的這樣就直接回溯了嗎?

  • case4

走到3的時候,遍歷5,6,但是發現回溯后走的是9并沒有比8小,也是應該不回溯的

綜上,只有環邊是最大邊且比回溯后走的第一條邊大的時候才會選擇回溯

#include <cstdio> #include <vector> #include <cstring> #include <algorithm> using namespace std; #define maxn 500005 vector < int > ans; struct node { int u, v; }edge[maxn << 1]; int head[maxn], to[maxn << 2], nxt[maxn << 2], f[maxn]; bool vis[maxn], circle[maxn]; bool flag1, flag2, flag3; int n, m, cnt, Max;void dfs1( int u ) {vis[u] = 1;ans.push_back( u );for( int i = head[u];~ i;i = nxt[i] ) {int v = to[i];if( vis[v] ) continue;else dfs1( v );} }void dfs2( int now, int fa ) {if( flag2 ) return;if( ! f[now] ) f[now] = fa;else {do {circle[fa] = 1;fa = f[fa];} while( fa ^ f[now] );flag2 = 1;return;}for( int i = head[now];~ i;i = nxt[i] )if( to[i] ^ fa ) dfs2( to[i], now ); }void dfs3( int u ) {vis[u] = 1;ans.push_back( u );if( circle[u] ) {bool flag = 0;for( int i = head[u];~ i;i = nxt[i] ) {if( flag3 ) break;if( ! circle[to[i]] or vis[to[i]] ) continue;int v = to[i];i = nxt[i];while( vis[to[i]] ) i = nxt[i];if( ~ i ) Max = to[i];else if( v > Max ) flag = flag3 = 1;break;}for( int i = head[u];~ i;i = nxt[i] ) if( vis[to[i]] or ( flag and circle[to[i]] ) ) continue;else dfs3( to[i] );}elsefor( int i = head[u];~ i;i = nxt[i] )if( vis[to[i]] ) continue;else dfs3( to[i] ); }int main() {scanf( "%d %d", &n, &m );if( m == n - 1 ) flag1 = 1;for( int i = 1, u, v;i <= m;i ++ ) {scanf( "%d %d", &u, &v );edge[i] = { u, v };edge[i + m] = { v, u };}m <<= 1;sort( edge + 1, edge + m + 1, []( node x, node y ) { return x.v > y.v; } );memset( head, -1, sizeof( head ) );for( int i = 1;i <= m;i ++ ) {int u = edge[i].u, v = edge[i].v;to[cnt] = v, nxt[cnt] = head[u], head[u] = cnt ++;}if( flag1 ) dfs1( 1 );else {dfs2( 1, 0 );Max = 1e9;dfs3( 1 );}for( auto i : ans ) printf( "%d ", i );return 0; }

CF1454E Number of Simple Paths

CF1454E

非常簡單

跑出環和非環樹

  • 兩個點隸屬于同一個環點的非環樹(之間不會經過環)
    • 從子樹大小中選兩個數,siz?(siz?1)/2siz*(siz-1)/2siz?(siz?1)/2
  • 經過環的兩點之間的方案數有兩種(走環的不同方向)
    • 從子樹中選一個,在子樹外選一個,siz?(n?siz)/2?2=siz?(n?siz)siz*(n-siz)/2*2=siz*(n-siz)siz?(n?siz)/2?2=siz?(n?siz)
#include <cstdio> #include <vector> using namespace std; #define int long long #define maxn 200005 vector < int > G[maxn]; int T, n; bool flag; int f[maxn], siz[maxn]; bool circle[maxn];void dfs1( int u, int fa ) {if( flag ) return;if( ! f[u] ) f[u] = fa;else {do {circle[fa] = 1;fa = f[fa];} while( f[u] ^ fa );flag = 1;return;}for( auto v : G[u] ) if( v ^ fa ) dfs1( v, u ); }void dfs2( int u, int fa ) {siz[u] = 1;for( auto v : G[u] ) {if( v == fa or circle[v] ) continue;else dfs2( v, u ), siz[u] += siz[v];} }signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld", &n );flag = 0;for( int i = 1;i <= n;i ++ ) circle[i] = f[i] = 0, G[i].clear();for( int i = 1, u, v;i <= n;i ++ ) {scanf( "%lld %lld", &u, &v );G[u].push_back( v );G[v].push_back( u );}dfs1( 1, 0 );int ans = 0;for( int i = 1;i <= n;i ++ )if( circle[i] ) {dfs2( i, 0 );ans += siz[i] * ( siz[i] - 1 ) / 2 + siz[i] * ( n - siz[i] );}printf( "%lld\n", ans );}return 0; }

Traffic Network in Numazu

HDU6393

同樣的,斷環為鏈

兩點間的距離分為三種

  • 兩點在同一棵非環樹內,直接求出兩個點的lca,再計算
  • 經過環
    • 兩點到環的兩端,然后加上斷的邊長
    • 兩點到環的相反兩端,然后加上斷的邊長

利用線段樹可以維護,但是樹狀數組更好寫

斷樹后進行dfn序的重置,修改一條邊其實是對于一個連續區間的修改

#include <cstdio> #include <vector> #include <iostream> using namespace std; #define int long long #define maxn 100005 struct node { int u, v, w; }E[maxn]; vector < node > G[maxn]; int Ti, n, Q, cnt, S, T, id, len; int L[maxn], R[maxn], t[maxn], f[maxn], dep[maxn]; int p[maxn][20];int lowbit( int i ) { return i & -i; }void modify( int i, int val ) {for( ;i <= n;i += lowbit( i ) ) t[i] += val; }int query( int i ) {int ans = 0;for( ;i;i -= lowbit( i ) )ans += t[i];return ans; }int find( int x ) { return x == f[x] ? x : f[x] = find( f[x] ); }void dfs( int u, int fa, int w ) {dep[u] = dep[fa] + 1;p[u][0] = fa;for( int i = 1;i < 20;i ++ )p[u][i] = p[p[u][i - 1]][i - 1];L[u] = ++ cnt;modify( L[u], w );for( auto i : G[u] )if( i.v ^ fa ) dfs( i.v, u, i.w );R[u] = cnt;modify( R[u] + 1, -w ); }int lca( int u, int v ) {if( dep[u] < dep[v] ) swap( u, v );for( int i = 19;~ i;i -- )if( dep[p[u][i]] >= dep[v] )u = p[u][i];if( u == v ) return u;for( int i = 19;~ i;i -- )if( p[u][i] ^ p[v][i] )u = p[u][i], v = p[v][i];return p[u][0]; }int dis( int x, int y ) {return query( L[x] ) + query( L[y] ) - query( L[lca( x, y )] ) * 2; }signed main() {scanf( "%lld", &Ti );while( Ti -- ) {scanf( "%lld %lld", &n, &Q );cnt = 0;for( int i = 1;i <= n;i ++ ) {G[i].clear();f[i] = i;t[i] = 0;for( int j = 0;j < 20;j ++ )p[i][j] = 0;}for( int i = 1, u, v, w;i <= n;i ++ ) {scanf( "%lld %lld %lld", &u, &v, &w );if( find( u ) == find( v ) )S = u, T = v, id = i, len = w;else {G[u].push_back( { u, v, w } );G[v].push_back( { v, u, w } );E[i] = { u, v, w };f[find( v )] = find( u );}}dfs( 1, 0, 0 ); for( int i = 1, opt, x, y;i <= Q;i ++ ) {scanf( "%lld %lld %lld", &opt, &x, &y );if( ! opt ) if( x == id ) len = y;else {int now = p[E[x].u][0] == E[x].v ? E[x].u : E[x].v;modify( L[now], y - E[x].w );modify( R[now] + 1, E[x].w - y );E[x].w = y;}else printf( "%lld\n", min( dis( x, y ), min( dis( x, S ) + dis( y, T ), dis( x, T ) + dis( y, S ) ) + len ) );}}return 0; }

Card Game

HDU6403


一張牌的兩面,要求朝上面的數字互不相同

顯然是將牌的兩面連邊,一條邊也就代表一張牌,數字互不相同就是選擇不同的點

  • 對于“樹”的方案
    • 欽定其中某個點不選,則剩下的點都被欽定,方案數為樹的大小
  • 對于“環”的方案
    • 只有兩種方案(均選左和均選右)

這是很基礎的“牌的兩面”基環樹應用的處理方法


轉回此題,題目可以翻譯為

將牌的反面向正面連邊,求反轉最少邊數的方案數,使得每個點的入度不超過1

顯然當且僅當圖為樹或基環樹的時候才有解

且此題很有可能有重邊和自環

同樣的將環拆成鏈后再單獨考慮被強斷的那條邊的貢獻

對于樹就單純的樹形DPDPDP

具體而言

  • 求出每個連通塊的點數和邊數

  • 若邊數不是點數或者點數減一,就無解

  • 若邊數等于點數,說明是個基環樹

    • 斷開一條邊后以邊的兩端開始遍歷一遍分別求出最少反轉的邊數

      (邊數跟連邊的邊權有關,下面有闡釋)

    • 如果加上這條邊的貢獻相同方案數為2,否則為1

  • 若邊數等于點數減一,說明是個普通的樹

    • 樹形DPDPDP,求出以每個點為根(欽定不選)的最少反轉次數

    • 其實最少反轉數在換根DPDPDP父親向兒子轉移的時候才會發生變化,且變化只有111

      如何根據邊權推測變化+1或者-1

      • 對于一張牌,正面向反面建邊權為1,反面向正面建邊權為0
      • uuu不選時的答案為dpudp_udpu?,轉移到兒子vvv不選時
      • 如果u→vu\rightarrow vuv的邊權為1,說明一張牌本來是uuu在上,dpudp_udpu?為了不選uuu將其反轉了
      • 那么變成不選vvv時,就需要選擇uuu,這張牌就變成了不反轉,操作次數就減一
      • 所以dpv=dpu?1dp_v=dp_u-1dpv?=dpu??1
      • 反之自然是dpv=dpu+1dp_v=dp_u+1dpv?=dpu?+1
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define int long long #define mod 998244353 #define maxn 200005 int Case, n, node, edge, cnt, S, T, id, top; int head[maxn], to[maxn], nxt[maxn], w[maxn], f[maxn], g[maxn], dp[maxn]; bool vis[maxn];void dfs1( int now ) {vis[now] = 1;node ++;for( int i = head[now];~ i;i = nxt[i] ) {edge ++;if( ! vis[to[i]] ) dfs1( to[i] );} }void dfs2( int now, int ID ) {vis[now] = 1;f[now] = 0;for( int i = head[now];~ i;i = nxt[i] ) {if( i == ID ) continue;if( ! vis[to[i]] ) {dfs2( to[i], i ^ 1 );f[now] += f[to[i]] + w[i];}else S = now, T = to[i], id = i;} }void dfs3( int now, int ID ) {dp[++ top] = g[now];for( int i = head[now];~ i;i = nxt[i] )if( i == ID or i == ( id ^ 1 ) or i == id ) continue;else {g[to[i]] = g[now] + ( w[i] ? -1 : 1 );dfs3( to[i], i ^ 1 );} }signed main() {scanf( "%lld", &Case );nxt :while( Case -- ) {scanf( "%lld", &n );memset( head, -1, sizeof( head ) );memset( vis, 0, sizeof( vis ) );cnt = 0;for( int i = 1, x, y;i <= n;i ++ ) {scanf( "%lld %lld", &x, &y );w[cnt] = 1, to[cnt] = y, nxt[cnt] = head[x], head[x] = cnt ++;w[cnt] = 0, to[cnt] = x, nxt[cnt] = head[y], head[y] = cnt ++;}for( int i = 1;i <= n;i ++ )if( ! vis[i] ) {node = edge = 0;dfs1( i );edge >>= 1;if( edge > node ) {printf( "-1 -1\n" );goto nxt;}}memset( vis, 0, sizeof( vis ) );int ret = 0, ans = 1; n <<= 1;for( int i = 1;i <= n;i ++ )if( ! vis[i] ) {S = T = cnt = top = 0, id = -1;dfs2( i, -1 );g[i] = f[i];dfs3( i, -1 );if( ! S ) {sort( dp + 1, dp + top + 1 );for( int j = 1;j <= top;j ++ )if( dp[j] == dp[1] ) cnt ++;else break;ret += dp[1];}else {id &= 1;if( g[S] + id == g[T] + ( id ^ 1 ) ) cnt = 2;else cnt = 1;ret += min( g[S] + id, g[T] + ( id ^ 1 ) );}ans = ans * cnt % mod;}printf( "%lld %lld\n", ret, ans );}return 0; }

總結

以上是生活随笔為你收集整理的数据结构之基环树——骑士,Island,旅行加强版,Number of Simple Paths,Traffic Network in Numazu,Card Game的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 在线无遮挡 | 曰女同女同中文字幕 | 五月天丁香在线 | 少妇天堂网 | 欧美 日韩 国产 在线 | 黄色片网站在线 | 奇米第四色在线 | 国产精品精品视频 | 亚洲免费看片 | 亚洲av综合一区 | 亚洲码欧美码一区二区三区 | 一本久道在线 | 欧美偷拍综合 | 久久久久久久久成人 | 国产精品无码久久久久一区二区 | 日日夜夜操操 | 白又丰满大屁股bbbbb | 成人免费毛片嘿嘿连载视频 | 国产精品一线二线三线 | 不卡视频国产 | 久久久久成人精品无码 | 午夜黄视频 | 国产哺乳奶水91在线播放 | 鲁鲁狠狠狠7777一区二区 | 特黄三级又爽又粗又大 | www.成人av| 久久久久久人妻一区二区三区 | 欧美a级片视频 | 色呦呦在线| 波多野结衣一区二区在线 | 中文字幕一区二区三区人妻四季 | 麻豆三级在线观看 | 成人三级在线看 | 日本一区二区三区四区视频 | 加勒比成人av | 天天躁夜夜躁 | 成人免费视频一区二区三区 | 蜜桃精品成人影片 | 九九在线免费视频 | 精品夜夜澡人妻无码av | 91精品人妻一区二区三区果冻 | 免费视频二区 | 日韩色| 亚洲av成人无码久久精品老人 | 国产内射合集颜射 | 无码人妻精品一区二区三应用大全 | 国产精品18久久久久久无码 | 亚洲美免无码中文字幕在线 | 蜜臀99久久精品久久久久小说 | 国产精一区 | 99久久久无码国产精品性 | 日本少妇中文字幕 | 亚洲美女性视频 | 黄色成人在线免费观看 | 免费av软件 | 亚洲在线一区二区三区 | 国产v片| 色窝窝无码一区二区三区 | 五十路japanese55丰满 | 三级黄色小视频 | 成av在线 | 久久综合操 | 精品久久久久久中文字幕人妻最新 | 香蕉视频在线视频 | 日韩精品无码一区二区三区 | 大奶骚| 久久久久久久久久久免费 | 精品一区二区三区毛片 | 日本激情一区二区 | 欧美亚洲综合视频 | 国产一区免费在线观看 | 91精品福利视频 | 高潮无码精品色欲av午夜福利 | 久久久久久久久久影视 | 亲嘴扒胸摸屁股激烈网站 | 美女扒开内裤让男人捅 | 婷婷激情在线 | 国产福利短视频 | 狠狠操狠狠操 | 色老大影院| 国产日产精品一区 | 1级黄色大片儿 | 亚洲免费a | 欧美三级视频网站 | 亚洲激情黄色 | 国产后入又长又硬 | 91福利在线免费观看 | 亚洲激情成人 | 草莓视频一区二区三区 | 黄色动漫软件 | 午夜激情久久 | 欧美50p| 欧美人日b | 黑人巨大猛交丰满少妇 | 91青青青 | 亚洲第九十七页 | 色偷偷一区二区三区 | 涩涩五月天 | 久久亚洲精少妇毛片午夜无码 |