标签:
1.OJ1278战略游戏
f[u][0]代表以u为根的子树,u不放时,最少放置节点数。
f[u][1]代表以u为根的子树,u放时,最少放置节点数。
f[u][0]=Σf[son][1]。
f[u][1]=Σmin(f[son][1],f[son][0])。
ans=min(f[root][0],f[root][1])。
#include<cstdio> #include<iostream> using namespace std; const int maxn=1500; int n,root,tot,ans; int pre[maxn],now[maxn],son[maxn],f[maxn][2]; inline void read(int &x){ char ch; x=0; while (ch=getchar(),ch==‘ ‘||ch==‘\n‘); while (isdigit(ch)){ x=x*10+ch-‘0‘; ch=getchar(); } } inline void build(int u,int v){ pre[++tot]=now[u]; now[u]=tot; son[tot]=v; } void search(int u){ f[u][1]=1; int p=now[u]; while (p){ int v=son[p]; search(v); f[u][1]+=min(f[v][1],f[v][0]); f[u][0]+=f[v][1]; p=pre[p]; } } void init(){ read(n); root=(n-1)*n/2; int u,k,v; for (int i=1;i<=n;++i){ read(u),read(k); for (int j=1;j<=k;++j) read(v),root-=v,build(u,v); } } void work(){ search(root); ans=min(f[root][0],f[root][1]); printf("%d\n",ans); } int main(){ init(); work(); return 0; }
2.OJ1264[Ural1018 ]二叉苹果树
f[u][i]代表以u为根的子树,保留i条边,最多能留下的苹果数。
f[u][0]=0。
枚举son,逆枚举i,f[u][i]=max(f[u][i],f[son][j]+f[u][i-j-1])。
ans=f[root][q]。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=115; int n,q,tot,now[maxn],pre[maxn<<1],son[maxn<<1],val[maxn<<1]; void connect(int u,int v,int w){pre[++tot]=now[u];now[u]=tot;son[tot]=v;val[tot]=w;} void init(){ scanf("%d%d",&n,&q); for (int u,v,w,i=1;i<=n-1;++i){ scanf("%d%d%d",&u,&v,&w); connect(u,v,w);connect(v,u,w); } } int f[maxn][maxn]; void tree_dp(int u,int fa){ f[u][0]=0; for (int p=now[u];p;p=pre[p]){ if (son[p]==fa) continue; tree_dp(son[p],u); for (int i=q;i>=1;--i) for (int j=0;j<=i-1;++j) f[u][i]=max(f[u][i],f[son[p]][j]+f[u][i-j-1]+val[p]); } } void work(){ memset(f,200,sizeof(f)); tree_dp(1,0); printf("%d\n",f[1][q]); } int main(){ init(); work(); return 0; }
3.OJ1277有线电视网
f[u][i]代表以u为根的子树,满足子树中i个叶子节点,所获得最大的收益。
f[u][0]=0。
如果u是叶子节点,f[u][1]=v[u]。
否则,枚举son,逆枚举i,f[u][i]=max(f[u][i],f[son][j]-val[p]+f[u][i-j])。
注意j只需枚举到以son为根的子树的叶子数目即可,i=∑leaf_num(当前已枚举到的son)。
还可以将son按leaf_num排序从小到大排序,会快一些,但我并不会算复杂度。
ans=最大的i,满足f[root][i]>=0。
#include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=3e3+15; typedef pair<int,int> PII; int n,m,v[maxn];vector<PII> g[maxn]; void init(){ scanf("%d%d",&n,&m); for (int tot,i=1;i<=n-m;++i){ scanf("%d",&tot); for (int a,c,j=1;j<=tot;++j){ scanf("%d%d",&a,&c); g[i].push_back(make_pair(a,c)); } } for (int i=n-m+1;i<=n;++i) scanf("%d",&v[i]); } int f[maxn][maxn]; int tree_dp(int u){ f[u][0]=0; if (u>=n-m+1){f[u][1]=v[u];return 1;} int s,sum=0; for (unsigned int i=0;i<g[u].size();++i){ sum+=(s=tree_dp(g[u][i].first)); for (int j=sum;j>=1;--j) for (int k=1;k<=min(j,s);++k) f[u][j]=max(f[u][j],f[u][j-k]+f[g[u][i].first][k]-g[u][i].second); } return sum; } void work(){ memset(f,200,sizeof(f)); tree_dp(1); for (int i=m;i>=0;--i) if (f[1][i]>=0){ printf("%d\n",i); break; } } int main(){ init(); work(); return 0; }
4.OJ1274“访问”艺术馆
f[u][i]代表以u为根的子树,花费了i的时间,所获得最大收益。
如果i是叶子节点,背包即可。
否则,枚举son,逆枚举i,f[u][i]=max(f[u][i],f[son][j]+f[u][i-j-2*val[p]])。
#include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef pair<int,int> PII; const int maxn=615,maxt=615; vector<PII> node[maxn]; int tim,cnt,len[maxn],son[maxn][2]; void init(int u){ int t,x;scanf("%d%d",&t,&x);len[u]=t; if (!x){init(son[u][0]=++cnt);init(son[u][1]=++cnt);} else{ for (int w,c,i=1;i<=x;++i){ scanf("%d%d",&w,&c); node[u].push_back(make_pair(w,c)); } } } int f[maxn][maxt]; void tree_dp(int u){ if (node[u].empty()){ tree_dp(son[u][0]); tree_dp(son[u][1]); for (int i=1;i<=tim;++i) for (int j=0;j<=i;++j){ int t=0; if (j>=2*len[son[u][0]]) t+=f[son[u][0]][j-2*len[son[u][0]]]; if (i-j>=2*len[son[u][1]]) t+=f[son[u][1]][i-j-2*len[son[u][1]]]; f[u][i]=max(f[u][i],t); } } else{ for (unsigned int i=0;i<node[u].size();++i) for (int j=tim;j>=node[u][i].second;--j) f[u][j]=max(f[u][j],f[u][j-node[u][i].second]+node[u][i].first); } } int main(){ scanf("%d",&tim);init(cnt=1); tim-=len[1]*2;tree_dp(1); printf("%d",f[1][tim-1]); return 0; }
5.OJ1216[Ioi2005]River
dis[u][j]代表u向上走j步的距离。
f[u][i][j]代表以u为根的子树建了i个伐木场(不包括u节点的),到跟的路径上第一个伐木场是u的第j个祖先。
枚举每个儿子,逆枚举i,
f[u][i][j]=min(f[u][i][j],f[son][k][j+1]+w[son]*dis[son][j+1]+f[u][i-k][j])。
if (i>k) f[u][i][j]=min(f[u][i][j],f[son][k][0]+f[u][i-k-1][j])。
ans=f[root][m][0]。
#include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=115,maxk=65; vector<int> g[maxn]; int n,m,w[maxn],fa[maxn],len[maxn]; void init(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;++i){ scanf("%d%d%d",&w[i],&fa[i],&len[i]); g[fa[i]].push_back(i); } } typedef unsigned int uint; int dis[maxn],anc[maxn][maxn]; void prepare(int u,int dep){ anc[u][1]=fa[u];dis[u]=dis[fa[u]]+len[u]; for (int i=2;i<=dep;++i) anc[u][i]=anc[fa[u]][i-1]; for (uint i=0;i<g[u].size();++i) prepare(g[u][i],dep+1); } const int inf=1e9; int f[maxn][maxk][maxn],t[maxn][maxk][maxn]; void tree_dp(int u,int dep){ for (uint i=0;i<g[u].size();++i){ int v=g[u][i]; tree_dp(v,dep+1); for (int l=0;l<=dep;++l) for (int j=0;j<=m;++j){ f[u][j][l]=inf; for (int k=0;k<=j;++k){ if (j-k>0) f[u][j][l]=min(f[u][j][l],t[u][j-k-1][l]+f[v][k][0]); f[u][j][l]=min(f[u][j][l],t[u][j-k][l]+f[v][k][l+1]+w[v]*(dis[v]-dis[anc[v][l+1]])); } } memcpy(t[u],f[u],sizeof(t[u])); } } void work(){ prepare(0,0); tree_dp(0,0); printf("%d\n",f[0][m][0]); } int main(){ init(); work(); return 0; }
6.OJ2412[Ahoi99]圣诞树游戏
f[i]代表将i点亮所需最小电流。
对于节点u,将儿子按f[son]从大到小排序,f[u]=max(f[u],f[son]+当前已枚举儿子数(不包括当前节点))。
ans=f[root]。
var x,n,m,j,k,i:longint; f:array[0..100] of longint; son:array[0..100,0..100] of longint; function max(p,q:longint):longint; begin if p>q then exit(p); exit(q); end; procedure sort(x,q:Longint); var t,i,j:longint; begin for i:=1 to q-1 do for j:=i+1 to q do if f[son[x,i]]<f[son[x,j]] then begin t:=f[son[x,i]]; f[son[x,i]]:=f[son[x,j]]; f[son[x,j]]:=t; end; end; procedure dfs(x:longint); var i:longint; begin for i:=1 to son[x,0] do dfs(son[x,i]); sort(x,son[x,0]); for i:=1 to son[x,0] do f[x]:=max(f[x],f[son[x,i]]+i-1); end; begin read(n); for i:=1 to n do begin read(x); inc(son[x,0]); son[x,son[x,0]]:=i; end; readln; for i:=1 to n do f[i]:=son[i,0]+1; dfs(1); writeln(f[1]); end.
7.OJ1217[baltic2003]gems
f[u][i]代表以u为根的子树,u节点数值为i,的最小数值和。
枚举son,枚举i,f[u][i]=min(f[son][j],j!=i)+i。
ans=min(f[root][i])。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=10015,maxm=5; int n,tot,now[maxn],pre[maxn<<1],son[maxn<<1]; void connect(int u,int v){pre[++tot]=now[u];now[u]=tot;son[tot]=v;} void init(){ scanf("%d",&n); for (int u,v,i=1;i<=n-1;++i){ scanf("%d%d",&u,&v); connect(u,v);connect(v,u); } } int f[maxn][maxm]; void tree_dp(int u,int fa){ static int g[maxm]; for (int i=1;i<maxm;++i) f[u][i]=i; for (int p=now[u];p;p=pre[p]){ if (son[p]==fa) continue; tree_dp(son[p],u); memset(g,64,sizeof(g)); for (int i=1;i<maxm;++i){ for (int j=1;j<maxm;++j) if (i!=j) g[i]=min(g[i],f[son[p]][j]); f[u][i]+=g[i]; } } } void work(){ tree_dp(1,0);int res=1e9; for (int i=1;i<maxm;++i) res=min(res,f[1][i]); printf("%d\n",res); } int main(){ init(); work(); return 0; }
8.OJ1326[Noi2003]逃学的小孩
对于树上三点a,b,c,求最大的dis[a][b]+dis[b][c],满足dis[a][b]<=dis[a][c]。
可以脑补dis[a][c]即为直径,a,c即为两端点,然后以a,c为源求disa,disc。
ans=max(dis[a][c]+min(dis[a][b],dis[c][b]))。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=2e5+15; typedef long long int64; int n,m,tot,now[maxn],pre[maxn<<1],son[maxn<<1],val[maxn<<1]; void connect(int u,int v,int w){pre[++tot]=now[u];now[u]=tot;son[tot]=v;val[tot]=w;} void init(){ scanf("%d%d",&n,&m); for (int u,v,w,i=1;i<=m;++i){ scanf("%d%d%d",&u,&v,&w); connect(u,v,w);connect(v,u,w); } } int fa[maxn],q[maxn];int64 dis[maxn]; void bfs(int s){ memset(dis,0,sizeof(dis)); int head=0,tail=1;q[1]=s;fa[s]=0; while (head!=tail){ int u=q[++head]; for (int p=now[u];p;p=pre[p]) if (son[p]!=fa[u]){ fa[son[p]]=u; q[++tail]=son[p]; dis[son[p]]=dis[u]+val[p]; } } } pair<int,int> node; void work(){ bfs(1);node.first=1; for (int i=2;i<=n;++i) if (dis[i]>dis[node.first]) node.first=i; bfs(node.first);node.second=1; for (int i=2;i<=n;++i) if (dis[i]>dis[node.second]) node.second=i; int64 d=dis[node.second]; static int64 dis1[maxn],dis2[maxn]; bfs(node.first);memcpy(dis1,dis,sizeof(dis)); bfs(node.second);memcpy(dis2,dis,sizeof(dis)); int64 res=0; for (int i=1;i<=n;++i) res=max(res,min(dis1[i],dis2[i])); printf("%I64d\n",res+d); } int main(){ init(); work(); return 0; }
9.OJ1218[balkan2002]Tribe council
UNsolved。
10.OJ1269OI队的回家路 Pku1947 Rebuilding Roads
f[u][i]代表以u为根的子树保留i个节点最少要切几条边。
f[u][1]=0。
枚举son,逆枚举i,另t=做当前儿子之前的f[u][i]
f[u][i]=min(t+1,f[u][j]+f[son][i-j])。
ans=min(f[root][p],min(f[u][p]+1))。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=215; int n,m,tot,root,now[maxn],pre[maxn],son[maxn]; void connect(int u,int v){pre[++tot]=now[u];now[u]=tot;son[tot]=v;} void init(){ scanf("%d%d",&n,&m);root=(n+1)*n/2; for (int u,v,i=1;i<=n-1;++i){ scanf("%d%d",&u,&v);root-=v; connect(u,v); } } int g[maxn][maxn],f[maxn][maxn]; void tree_dp(int u){ f[u][1]=0; for (int p=now[u];p;p=pre[p]){ tree_dp(son[p]); for (int i=m;i>=1;--i) for (int j=0;j<=i-1;++j) if (j) f[u][i]=min(f[u][i],f[u][j]+f[son[p]][i-j]); else f[u][i]=f[u][i]+1; } } void work(){ memset(g,63,sizeof(g)); memset(f,63,sizeof(f)); tree_dp(root); int res=f[root][m]; for (int i=1;i<=n;++i) res=min(res,f[i][m]+1); printf("%d\n",res); } int main(){ init(); work(); return 0; }
11.OJ2577[Nwerc2009]Moving to Nuremberg
预处理以u为根的子树中的标记次数sum[u],和标记点(多次要计算)到root的距离和dis[root]。
dis[son]=dis[u]-sum[son]*val[p]+(sum[root]-sum[son])*val[p]。
ans=min(dis[u])。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=5e4+15; typedef long long int64; int n,m,tot,tim[maxn],now[maxn],pre[maxn<<1],son[maxn<<1],val[maxn<<1]; void connect(int u,int v,int w){pre[++tot]=now[u];now[u]=tot;son[tot]=v;val[tot]=w;} int head,tail,q[maxn],fa[maxn];int64 tottim,f[maxn],v[maxn],sdis[maxn],stim[maxn]; void get_sum_dist(){ q[1]=1;fa[1]=0;head=0;tail=1; memset(sdis,0,sizeof(int64)*(n+1)); memset(stim,0,sizeof(int64)*(n+1)); while (head!=tail){ int u=q[++head]; for (int p=now[u];p;p=pre[p]) if (son[p]!=fa[u]){ q[++tail]=son[p]; v[son[p]]=val[p]; fa[son[p]]=u; } } for (int i=tail;i>=1;--i){ int u=q[i]; stim[u]=tim[u]; for (int p=now[u];p;p=pre[p]){ stim[u]+=stim[son[p]]; sdis[u]+=stim[son[p]]*val[p]+sdis[son[p]]; } } } void get_ans(){ f[1]=sdis[1]; for (int i=2;i<=tail;++i){ int u=q[i]; f[u]=f[fa[u]]-stim[u]*v[u]+(tottim-stim[u])*v[u]; } int64 res=f[1]; for (int i=2;i<=n;++i) res=min(res,f[i]); printf("%I64d\n",2*res); for (int i=1;i<=n;++i) if (f[i]==res) printf("%d ",i); putchar(‘\n‘); } void solve(){ scanf("%d",&n);tot=tottim=0; memset(now,0,sizeof(int)*(n+1)); for (int u,v,w,i=1;i<=n-1;++i){ scanf("%d%d%d",&u,&v,&w); connect(u,v,w);connect(v,u,w); } scanf("%d",&m); memset(tim,0,sizeof(int)*(n+1)); for (int x,f,i=1;i<=m;++i){ scanf("%d%d",&x,&f); tim[x]=f;tottim+=f; } get_sum_dist(); get_ans(); } int main(){ int cases;scanf("%d",&cases); for (int i=1;i<=cases;++i) solve(); return 0; }
12.OJ1213[zjoi2007]时态同步
贪心,求出u到叶子的最远距离fmx[u],res+=Σ(fmx[u]-fmx[son[p]]+val[p])。
ans=res。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=500015; int n,s,tot,now[maxn],pre[maxn<<1],son[maxn<<1],val[maxn<<1]; void connect(int u,int v,int w){pre[++tot]=now[u];now[u]=tot;son[tot]=v;val[tot]=w;} void init(){ scanf("%d%d",&n,&s); for (int u,v,w,i=1;i<=n-1;++i){ scanf("%d%d%d",&u,&v,&w); connect(u,v,w);connect(v,u,w); } } long long ans; int maxdis[maxn];//std ????long long ??RZ void greedy(int u,int f){ for (int p=now[u];p;p=pre[p]) if (son[p]!=f){ greedy(son[p],u); maxdis[u]=max(maxdis[u],maxdis[son[p]]+val[p]); } for (int p=now[u];p;p=pre[p]) if (son[p]!=f) ans+=maxdis[u]-(maxdis[son[p]]+val[p]); } void work(){ greedy(s,0); printf("%I64d\n",ans); } int main(){ init(); work(); return 0; }
13.OJ1280[Noi2008]道路设计
f[u][i][j],j=0,1,2,代表以u为根的子树,u向下连了j条边,答案为i的方案数。
f[u][i][0]=Π(f[son][i-1][0]+f[son][i-1][1]+f[son][i-1][2])。
f[u][i][1]=Σ{(f[son][i][0]+f[son][i][1])Π(f[son‘][i-1][0]+f[son‘][i-1][1]+f[son‘][i-1][2])}。
f[u][i][2]=ΣΣ{(f[son][i][0]+f[son][i][1]+f[son‘][i][0]+f[son‘][i][1])Π(f[son‘‘][i-1][0]+f[son‘‘][i-1][1]+f[son‘‘][i-1][2])}。
令f0=f[son][i-1][0]+f[son][i-1][1]+f[son][i-1][2],f1=f[son][i][0]+f[son][i][1]。
则f[u][i][0]=Πf0,f[u][i][1]=Σ(f1Πf0‘),f[u][i][2]=ΣΣ(f1f1‘Πf0‘‘)。
枚举每个son,考虑每次带来的新贡献,则有,
f[u][i][0]=f[u][i][0]‘*f0。
f[u][i][1]=f1*f[u][i][0]‘+f0*f[u][i][1]‘。
f[u][i][2]=f1*f[u][i][1]‘+f0*f[u][i][2]‘。
ans=最大的i,满足max(f[root][i][0],f[root][i][1],f[root][i][2])>0。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=1e5+15; typedef long long int64; int64 n,m,q,tot,now[maxn],pre[maxn<<1],son[maxn<<1]; void connect(int u,int v){pre[++tot]=now[u];now[u]=tot;son[tot]=v;} void init(){ scanf("%lld%lld%lld",&n,&m,&q); if (m!=n-1){printf("-1\n-1\n");exit(0);} for (int u,v,i=1;i<=n-1;++i){ scanf("%d%d",&u,&v); connect(u,v);connect(v,u); } } const int max_ans=15; int64 f[maxn][max_ans][3];//代表以i为根的子树,当前答案为j,且根向下连了k条边的方案数 /* f[i][j][0]=PI(f[son][j-1][0]+f[son][j-1][1]+f[son][j-1][2]); f[i][j][1]=SIGMA((f[son][j][0]+f[son][j][1])*PI(f[son‘][j-1][0]+f[son‘][j-1][1]+f[son‘][j-1][2])); f[i][j][2]=SIGMA((f[son][j][0]+f[son][j][1])*(f[son‘][j][0]+f[son‘][j][1])*PI(f[son‘‘][j-1][0]+f[son‘‘][j-1][1]+f[son‘‘][j-1][2])); 令f1=f[son][j-1][0]+f[son][j-1][1]+f[son][j-1][2],f2=f[son][j][0]+f[son][j][1] f[i][j][0]=PI(f1); f[i][j][1]=SIGMA(f2*PI(f1)); f[i][j][2]=SIGMA(f2*f2*PI(f1)); for each son f[i][j][2]=f[i][j][2]*f1+f[i][j][1]*f2; f[i][j][1]=f[i][j][1]*f1+f[i][j][0]*f2; f[i][j][0]*=f1; */ int64 get(int64 x){return !(x%q)&&x?q:x%q;} void tree_dp(int u,int fa){ for (int i=0;i<max_ans;++i) f[u][i][0]=1; for (int p=now[u];p;p=pre[p]){ if (son[p]==fa) continue; tree_dp(son[p],u); for (int i=0;i<max_ans;++i){ int64 f1=i?f[son[p]][i-1][0]+f[son[p]][i-1][1]+f[son[p]][i-1][2]:0; int64 f2=f[son[p]][i][0]+f[son[p]][i][1]; f[u][i][2]=get(f[u][i][2]*f1+f[u][i][1]*f2); f[u][i][1]=get(f[u][i][1]*f1+f[u][i][0]*f2); f[u][i][0]=get(f[u][i][0]*f1); } } } void work(){ tree_dp(1,0); for (int i=0;i<max_ans;++i){ int64 t=f[1][i][0]+f[1][i][1]+f[1][i][2]; if (t>0){printf("%d\n%d\n",i,(int)(t%q));exit(0);} } printf("-1\n-1\n"); } int main(){ init(); work(); return 0; }
14.OJ3155[CQOI2009]叶子的染色
f[u][i],代表以u为根的子树颜色为i(当i=2时所有颜色均满足)的节点全部满足的最小染色数。
若u为叶子,f[u][c[u]]=1,f[u][c[u]^1]=0,f[u][2]=1。
否则,枚举son,设t0,t1,t2
t0=∑f[son][0]。
t1=∑f[son][1]。
t2=∑f[son][2]。
f[u][2]=min(t0+1,t1+1,t2)。
f[u][0]=min(t0,t1+1,f[u][2])。
f[u][1]=min(t1,t0+1,f[u][2])。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxm=1e4+15,maxn=6e3+15; int m,n,tot,c[maxm],now[maxm],pre[maxm<<1],son[maxm<<1]; void connect(int u,int v){pre[++tot]=now[u];now[u]=tot;son[tot]=v;} void init(){ scanf("%d%d",&m,&n); for (int i=1;i<=n;++i) scanf("%d",&c[i]); for (int u,v,i=1;i<=m-1;++i){ scanf("%d%d",&u,&v); connect(u,v);connect(v,u); } } int f[maxm][3];//0 只满足0 1 只满足1 2 全满足 的 最小花费 void tree_dp(int u,int fa){ if (u<=n){ f[u][2]=1; f[u][c[u]]=1; f[u][c[u]^1]=0; return; } int sum0=0,sum1=0,sum2=0; for (int p=now[u];p;p=pre[p]){ if (son[p]==fa) continue; tree_dp(son[p],u); sum0+=f[son[p]][0]; sum1+=f[son[p]][1]; sum2+=f[son[p]][2]; } f[u][2]=min(sum2,min(sum0,sum1)+1); f[u][0]=min(f[u][2],min(sum0,sum1+1)); f[u][1]=min(f[u][2],min(sum0+1,sum1)); } void work(){ tree_dp(n+1,-1); printf("%d\n",f[n+1][2]); } int main(){ init(); work(); return 0; }
待更新。
标签:
原文地址:http://www.cnblogs.com/iamCYY/p/4904572.html