第五次上机赛解题报告及标程
来源:互联网 发布:二进制转bcd码算法 编辑:程序博客网 时间:2024/05/21 17:33
这次上机的题目考查的内容以图论的一些基础算法为主,我实话实话这次上机题有出失误的地方,个别题的难度没有控制好,所以过题情况不佳也是情理之中。
A. 对称二叉树
与上一次上机的同构二叉树很相似,这不过这道题要求的是轴对称;事实上也只要在那道题的基础上改动几处代码就可以了。
#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;const int MAXN=1005;struct BTNode{ char data[10]; BTNode *lchild,*rchild;};char str[MAXN];void CreateBTNode(BTNode *&b){ BTNode *St[MAXN],*p; int top=-1,k,l=strlen(str); b=NULL; for(int i=0; i<l; ++i) switch(str[i]) { case '(': St[++top]=p; k=1; break; case ')': --top; break; case ',': k=2; break; default: p=(BTNode *)malloc(sizeof(BTNode)); int j=0; while(i<l&&str[i]!='('&&str[i]!=')'&&str[i]!=',') p->data[j++]=str[i++]; --i; p->data[j]='\0'; p->lchild=p->rchild=NULL; if(!b) b=p; else switch(k) { case 1: St[top]->lchild=p; break; case 2: St[top]->rchild=p; break; } }}bool Symm(BTNode *b1,BTNode *b2){ if(!b1&&!b2) return true; if(!b1||!b2) return false; if(strcmp(b1->data,b2->data)!=0) return false; return Symm(b1->lchild,b2->rchild)&&Symm(b1->rchild,b2->lchild);}bool Symmtree(BTNode *b){ if(!b) return true; return Symm(b->lchild,b->rchild);}void DestroyBT(BTNode *&b){ if(b->lchild) DestroyBT(b->lchild); if(b->rchild) DestroyBT(b->rchild); free(b);}int main(){ while(~scanf("%s",str)) { BTNode *b; CreateBTNode(b); puts(Symmtree(b)?"YES":"NO"); DestroyBT(b); }}
B. 拮据的模拟城市
这道题的题意其实非常明确,就是要求最小生成树的各边权值和。唯一要注意的是图中可以有重边,所以使用邻接矩阵建图时需要注意。
这里我给出kruskal和prim两种做法的标程。
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=1005;const int MAXM=100005;struct edge{ int u,v,w; edge(int _u=0,int _v=0,int _w=0):u(_u),v(_v),w(_w) {} bool operator<(const edge &oth) const { return w<oth.w; }} e[MAXM];int n,m;int u[MAXN];void init(){ for(int i=1; i<=n; ++i) u[i]=i;}int find(int x){ if(u[x]!=x) u[x]=find(u[x]); return u[x];}void merge(int x,int y){ u[find(x)]=find(y);}int kruskal(){ sort(e,e+m); int ret=0,cnt=0; init(); for(int i=0; cnt<n-1&&i<m; ++i) if(find(e[i].u)!=find(e[i].v)) { merge(e[i].u,e[i].v); ret+=e[i].w; ++cnt; } return ret;}int main(){ while(~scanf("%d%d",&n,&m)) { for(int i=0; i<m; ++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); printf("%d\n",kruskal()); }}
#include<cstdio>#include<cstring>using namespace std;const int MAXN=1005;const int INF=0x3f3f3f3f;int g[MAXN][MAXN],n,lowc[MAXN];int prim(){ for(int i=1; i<=n; ++i) lowc[i]=g[1][i]; int ret=0; for(int i=1; i<n; ++i) { int mark=-1,minc=INF; for(int j=1; j<=n; ++j) if(lowc[j]&&minc>lowc[j]) { minc=lowc[j]; mark=j; } ret+=minc; lowc[mark]=0; for(int j=1; j<=n; ++j) if(lowc[j]&&lowc[j]>g[mark][j]) lowc[j]=g[mark][j]; } return ret;}int main(){ int m,u,v,l; while(~scanf("%d%d",&n,&m)) { memset(g,0x3f,sizeof(g)); for(int i=1; i<=n; ++i) g[i][i]=0; while(m--) { scanf("%d%d%d",&u,&v,&l); if(l<g[u][v]) g[u][v]=g[v][u]=l; } printf("%d\n",prim()); }}
C. 迷宫里有一只薛定谔的猫!
这道题要求的,是从1点到其余所有点的最短距离的期望。所以跑一遍单源最短路就可以了,要注意的依然是重边问题。
关于单源最短路,书中只给出了dijkstra算法,事实上这不是唯一的单源最短路算法。我这里给出dijkstra+邻接矩阵和spfa+邻接表的两种标程。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=505;const int INF=0x3f3f3f3f;int g[MAXN][MAXN],dist[MAXN],n;bool vis[MAXN];void dijkstra(int src){ memset(dist,0x3f,sizeof(dist)); memset(vis,false,sizeof(vis)); dist[src]=0; for(int i=0; i<n; ++i) { pair<int,int> tmp=make_pair(INF,-1); for(int j=1; j<=n; ++j) if(!vis[j]&&dist[j]<tmp.first) tmp=make_pair(dist[j],j); if(!~tmp.second) break; vis[tmp.second]=true; for(int j=1; j<=n; ++j) dist[j]=min(dist[j],tmp.first+g[tmp.second][j]); }}int main(){ int m,a,b,l; while(~scanf("%d%d",&n,&m)) { memset(g,0x3f,sizeof(g)); for(int i=1; i<=n; ++i) g[i][i]=0; while(m--) { scanf("%d%d%d",&a,&b,&l); g[a][b]=min(g[a][b],l); } dijkstra(1); double ans=0; for(int i=1; i<=n; ++i) ans+=dist[i]; printf("%.2f\n",ans/(n-1)); }}
#include<cstdio>#include<cstring>#include<queue>using namespace std;const int MAXN=505;const int MAXM=MAXN*MAXN;struct graph{ int head[MAXN]; int to[MAXM]; int next[MAXM]; int len[MAXM]; int tot; void init() { tot=0; memset(head,0xff,sizeof(head)); } void add(int u,int v,int w) { to[tot]=v; len[tot]=w; next[tot]=head[u]; head[u]=tot++; }} g;int dist[MAXN];bool inque[MAXN];void spfa(int src){ memset(dist,0x3f,sizeof(dist)); memset(inque,false,sizeof(inque)); dist[src]=0; queue<int> q; q.push(src); inque[src]=true; while(!q.empty()) { int u=q.front(); q.pop(); inque[u]=false; for(int i=g.head[u]; ~i; i=g.next[i]) { int v=g.to[i]; if(dist[u]+g.len[i]<dist[v]) { dist[v]=dist[u]+g.len[i]; if(!inque[v]) { q.push(v); inque[v]=true; } } } }}int main(){ int n,m,a,b,l; while(~scanf("%d%d",&n,&m)) { g.init(); while(m--) { scanf("%d%d%d",&a,&b,&l); g.add(a,b,l); } spfa(1); double ans=0; for(int i=1; i<=n; ++i) ans+=dist[i]; printf("%.2f\n",ans/(n-1)); }}
另外说一句,设V是点数,E是边数;标准的dijkstra算法,使用邻接矩阵,复杂度是O(V^2)的,使用堆优化或者优先队列优化,再使用恰当的建图方式,可以有效降低复杂度。标准spfa算法,使用邻接表,复杂度大概是O(k*E),k根据图的不同,可能很小,也可能大到接近V,用某些优化方法可以使k减小。换言之,应该根据图的特性(稠密图?稀疏图?)来选择最合适的算法。
D. 迷宫里有两只薛定谔的猫!
这道题是求任意两点之间最短距离的期望。或许因为和上一题太像,许多人选择在每一个点上都跑一次dijkstra算法。方法上没有问题,但为什么不使用floyd算法呢……在多源最短路的问题上,floyd算法显然代码更短,效率更高。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=205;const int INF=0x3f3f3f3f;int g[MAXN][MAXN],n;void floyd(){ for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) g[i][j]=min(g[i][j],g[i][k]+g[k][j]);}int main(){ int m,a,b,l; while(~scanf("%d%d",&n,&m)) { memset(g,0x3f,sizeof(g)); for(int i=1; i<=n; ++i) g[i][i]=0; while(m--) { scanf("%d%d%d",&a,&b,&l); if(l<g[a][b]) g[a][b]=g[b][a]=l; } floyd(); double ans=0; for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) ans+=g[i][j]; printf("%.2f\n",ans/(n*(n-1))); }}
E. 迷宫里有一只深井冰!
这道题,大概是渣诚满满的恶意……这是一道基础的TSP旅行商问题,是一个NP问题,这也意味着它并没有多项式复杂度的解法,所以不属于各种最短路算法的范畴;从至多10个点的数据量大概也可以看出,我们只是想让大家写一发暴搜。
不过暴力也是有很多方法的,我的做法相当于取了个巧;假设从0点出发,用next_permutation()函数穷举出所有以0开头的排列,然后计算这种排列代表的走法的路径长度,取最短的即可。这样暴力的复杂度是O(n!)。
另外,这道题是可以状压dp的,可以把复杂度降到O(n^2*2^n),有兴趣的童鞋可以研究一下。简单地说,设从0点出发,dp(i,j)表示在状态i下访问到j点的最短路径长度,则dp((1<<n)-1,k)就表示遍历过所有点且以k点为终点的最短路径长度。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;int g[10][10],s[10];int main(){ int n; while(~scanf("%d",&n)) { for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) scanf("%d",&g[i][j]); for(int i=0; i<n; ++i) s[i]=i; int ans=INF; while(s[0]==0) { int tmp=g[s[n-1]][s[0]]; for(int i=1; i<n; ++i) tmp+=g[s[i-1]][s[i]]; ans=min(ans,tmp); next_permutation(s,s+n); } printf("%d\n",ans); }}
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;int g[10][10],dp[10][1<<10];int main(){ int n; while(~scanf("%d",&n)) { for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) scanf("%d",&g[i][j]); memset(dp,0x3f,sizeof(dp)); dp[0][1]=0; for(int i=1; i<(1<<n); i+=2) for(int j=0; j<n; ++j) if(i&(1<<j)) for(int k=0; k<n; ++k) if(!(i&(1<<k))) dp[k][i|(1<<k)]=min(dp[k][i|(1<<k)],dp[j][i]+g[j][k]); int ans=INF; for(int i=1; i<n; ++i) ans=min(ans,dp[i][(1<<n)-1]+g[i][0]); printf("%d\n",ans); }}
F. 结点距离下集
这是一道陈题,也是我觉得出题有失误的一道题。倒不是因为这道题所需知识超出了范围,而是这道题的题目描述相当不清晰。题目实际是在描述这样一个图,首先这个图是一个森林(对,没有环),在森林中的每棵树都有这样的特点,就是其中有一个节点是根节点(即题目中的集换中心),而其它节点的度(双向边,无所谓入度出度)小于等于2,形象一点地说,就是每一棵树都像神经元一样,根节点是细胞体,其余节点都在各条突触上,且每条突触不会分叉。
所以,在当前的知识储备下,做法就是先遍历整个森林,找到每棵树上的根节点(统计度数就可以了,如果所有节点的度数都小于等于2,则这棵树必定是一条链,可以任选一个节点作为根节点);然后,再从根节点出发,对每棵树进行遍历,并记录每个节点的深度,和所在链的编号。这样,任意一棵树中的两个节点,倘若在一条链上,其最小距离就是深度的差,倘若不在一条链上,其距离就是深度的和(因为要通过根节点)。放一下渣诚的标程作为参考。
//trashLHC#include<iostream>#include<cstdio>#include<cmath>#include<cstdlib>#define MAXV 100001int a[MAXV],b[MAXV];typedef struct ANode{ int adjvex; struct ANode *nextarc; int info; int router;}ArcNode;typedef struct Vnode{ int data; ArcNode *firstarc;}VNode;typedef VNode AdjList[MAXV];typedef struct{ AdjList adjlist; int n,e;}ALGraph;int visited[MAXV];void CreateList(ALGraph *&G,int n,int l){ int i,j; ArcNode *p,*q; G=(ALGraph *)malloc(sizeof(ALGraph)); for(i=0;i<=n;i++) G->adjlist[i].firstarc=NULL; for(i=0;i<l;i++) { p=(ArcNode *)malloc(sizeof(ArcNode)); p->adjvex=b[i]; p->nextarc=G->adjlist[a[i]].firstarc; G->adjlist[a[i]].firstarc=p; q=(ArcNode *)malloc(sizeof(ArcNode)); q->adjvex=a[i]; q->nextarc=G->adjlist[b[i]].firstarc; G->adjlist[b[i]].firstarc=q; } G->n=n;G->e=l;}int route=0;int length=0;int distance[MAXV];int rout[MAXV];void DFS(ALGraph *G,int v){ ArcNode *p,*q; visited[v]=1; p=G->adjlist[v].firstarc; p->router=route; p->info=length; distance[v]=p->info; rout[v]=p->router; while(p!=NULL) { if(!visited[p->adjvex]) break; p=p->nextarc; } if(p==NULL) { route++; length=0; } p=G->adjlist[v].firstarc; while(p!=NULL) { if(!visited[p->adjvex]) { length++; DFS(G,p->adjvex); } p=p->nextarc; }}void DetroyGraph(ALGraph *&G){ ArcNode *p,*q; for(int i=0;i<=G->n;i++) { p=G->adjlist[i].firstarc; while(p!=NULL) { q=p; p=p->nextarc; free(q); } } free(G);}int main(){ int t; scanf("%d",&t); while(t--) { int m,n; scanf("%d%d",&m,&n); ALGraph *G2; int max=0; int counter[MAXV]; for(int i=0;i<=m;i++) { counter[i]=0; distance[i]=0; rout[i]=0; visited[i]=0; } for(int i=0;i<m;i++) { scanf("%d%d",&a[i],&b[i]); counter[a[i]]++;counter[b[i]]++; } int recorder=0; for(int i=0;i<=m;i++) if(max<counter[i]) { recorder=i; max=counter[i]; } CreateList(G2,m,m); DFS(G2,recorder); for(int i=0;i<n;i++) { int temp1,temp2; scanf("%d%d",&temp1,&temp2); if(rout[temp1]==rout[temp2])printf("%d\n",abs(distance[temp1]-distance[temp2])); else printf("%d\n",distance[temp1]+distance[temp2]); } route=0; length=0; DetroyGraph(G2); }}
而我不是这么做的,我的做法超出了课程范围,不过适用范围会更广一些,只要保证图是一个森林就可以了,对每棵树的具体形状并没有要求,这里简单说一下供有兴趣的童鞋探究。我的做法是处理出树上任意两点的lca,即最近公共祖先,则这两点的距离就是这两点的深度之和减去2×最近公共祖先的深度。处理lca的方法有两种,一种是在线倍增法,复杂度是O(nlogn),一种是离线Tarjan算法,复杂度上O(n)。下面分别放出两种做法的标程。
//by wjfwzzc//lca+倍增#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=100005;const int MAXM=200005;const int maxd=17;struct graph{ int head[MAXN]; int to[MAXM]; int next[MAXM]; int tot; void init() { tot=0; memset(head,0xff,sizeof(head)); } void add(int u,int v) { to[tot]=v; next[tot]=head[u]; head[u]=tot++; }} g;int d[MAXN],f[MAXN][maxd];void dfs(int u,int fa){ f[u][0]=fa; for(int i=1; i<maxd; ++i) f[u][i]=f[f[u][i-1]][i-1]; for(int i=g.head[u]; ~i; i=g.next[i]) { int v=g.to[i]; if(v!=fa) { d[v]=d[u]+1; dfs(v,u); } }}int lca(int u,int v){ if(d[u]<d[v]) swap(u,v); int k=d[u]-d[v]; for(int i=0; i<maxd; ++i) if((1<<i)&k) u=f[u][i]; if(u==v) return u; for(int i=maxd-1; i>=0; --i) if(f[u][i]!=f[v][i]) { u=f[u][i]; v=f[v][i]; } return f[u][0];}int main(){ int t,m,n,a,b; scanf("%d",&t); while(t--) { g.init(); scanf("%d%d",&m,&n); while(m--) { scanf("%d%d",&a,&b); g.add(a,b); g.add(b,a); } d[0]=0; dfs(0,-1); while(n--) { scanf("%d%d",&a,&b); printf("%d\n",d[a]+d[b]-2*d[lca(a,b)]); } }}
//by wjfwzzc//lca+Tarjan#include<cstdio>#include<cstring>using namespace std;const int MAXN=100005;const int MAXM=200005;struct graph{ int head[MAXN]; int to[MAXM]; int idx[MAXM]; int next[MAXM]; int tot; void init() { tot=0; memset(head,0xff,sizeof(head)); } void add(int u,int v,int w=-1) { to[tot]=v; idx[tot]=w; next[tot]=head[u]; head[u]=tot++; }} g,q;int x[MAXN],y[MAXN],z[MAXN];int f[MAXN],d[MAXN];bool vis[MAXN];int find(int x){ if(f[x]!=x) return f[x]=find(f[x]); return f[x];}void tarjan(int u){ vis[u]=true; f[u]=u; for(int i=q.head[u]; ~i; i=q.next[i]) { int v=q.to[i]; if(vis[v]) z[q.idx[i]]=find(v); } for(int i=g.head[u]; ~i; i=g.next[i]) { int v=g.to[i]; if(!vis[v]) { d[v]=d[u]+1; tarjan(v); f[v]=u; } }}int main(){ int t,m,n,a,b; scanf("%d",&t); while(t--) { g.init(); scanf("%d%d",&m,&n); while(m--) { scanf("%d%d",&a,&b); g.add(a,b); g.add(b,a); } q.init(); for(int i=1; i<=n; ++i) { scanf("%d%d",&x[i],&y[i]); q.add(x[i],y[i],i); q.add(y[i],x[i],i); } memset(vis,false,sizeof(vis)); d[0]=0; tarjan(0); for(int i=1; i<=n; ++i) printf("%d\n",d[x[i]]+d[y[i]]-2*d[z[i]]); }}
G. Fibonacci Tree
这是我在2013年ACM成都现场赛做过的原题,网上自然有很多题解;但有十余位童鞋选择直接照搬网上代码还是很令人寒心。这道题是说权值只有1和0两种的一个图,问其是否存在权值和为Fibonacci数的生成树。直接做一遍最小生成树和最大生成树(最小生成树的两种算法本质都是贪心,所以可以很容易地改写出求最大生成树),然后注意到,我们假设把得到的最小生成树逐边修改得到最大生成树,在修改的过程中,必然会出现把0边改成1边这样的情况,换言之,最小生成树和最大生成树的权值之间形成的区间,一定是致密的,再换种说法,这个区间内任何一个值对应的生成树必然存在;所以,我们只要判断是否有Fibonacci数存在于这个区间内就可以了。所以最后的做法是预处理出一些Fibonacci数(30个左右即可),然后在求出最小生成树和最大生成树之后,穷举Fibonacci数进行判断即可。这里给出使用kruskal和prim两种算法的标程。
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=1005;const int MAXM=100005;struct edge{ int u,v,w; edge(int _u=0,int _v=0,int _w=0):u(_u),v(_v),w(_w) {}} e[MAXM];bool cmp1(const edge &a,const edge &b){ return a.w<b.w;}bool cmp2(const edge &a,const edge &b){ return a.w>b.w;}bool (*cmp[])(const edge&,const edge&)= {cmp1,cmp2};int n,m;int u[MAXN];void init(){ for(int i=1; i<=n; ++i) u[i]=i;}int find(int x){ if(u[x]!=x) u[x]=find(u[x]); return u[x];}void merge(int x,int y){ u[find(x)]=find(y);}int kruskal(int k){ sort(e,e+m,cmp[k]); int ret=0,cnt=0; init(); for(int i=0; cnt<n-1&&i<m; ++i) if(find(e[i].u)!=find(e[i].v)) { merge(e[i].u,e[i].v); ret+=e[i].w; ++cnt; } return cnt<n-1?-1:ret;}int main(){ int f[30]; f[0]=1; f[1]=2; for(int i=2; i<30; ++i) f[i]=f[i-1]+f[i-2]; while(~scanf("%d%d",&n,&m)) { for(int i=0; i<m; ++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); int amin=kruskal(0),amax=kruskal(1); bool flag=false; if(~amin&&~amax) for(int i=0; !flag&&i<30; ++i) if(amin<=f[i]&&amax>=f[i]) flag=true; puts(flag?"Yes":"No"); }}
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=1005;const int INF=0x3f3f3f3f;bool lvis[MAXN],hvis[MAXN];int g[MAXN][MAXN][2],n,lc[MAXN],hc[MAXN],amin,amax;void prim(){ memset(lvis,false,sizeof(lvis)); memset(hvis,false,sizeof(hvis)); for(int i=1; i<=n; ++i) { lc[i]=g[1][i][0]; hc[i]=g[1][i][1]; } lvis[1]=hvis[1]=true; amin=amax=0; for(int i=1; i<n; ++i) { int lmark=-1,hmark=-1,lminc=INF,hminc=-1; for(int j=1; j<=n; ++j) { if(!lvis[j]&&lminc>lc[j]) { lminc=lc[j]; lmark=j; } if(!hvis[j]&&hminc<hc[j]) { hminc=hc[j]; hmark=j; } } if(!~lmark) { amin=-1; break; } if(!~hmark) { amax=-1; break; } lvis[lmark]=hvis[hmark]=true; amin+=lc[lmark]; amax+=hc[hmark]; for(int j=1; j<=n; ++j) { if(!lvis[j]&&lc[j]>g[lmark][j][0]) lc[j]=g[lmark][j][0]; if(!hvis[j]&&hc[j]<g[hmark][j][1]) hc[j]=g[hmark][j][1]; } }}int main(){ int f[30]; f[0]=1; f[1]=2; for(int i=2; i<30; ++i) f[i]=f[i-1]+f[i-2]; int m,a,b,c; while(~scanf("%d%d",&n,&m)) { for(int i=1; i<=n; ++i) { for(int j=1; j<=n; ++j) { g[i][j][0]=INF; g[i][j][1]=-1; } g[i][i][0]=g[i][i][1]=0; } while(m--) { scanf("%d%d%d",&a,&b,&c); if(c<g[a][b][0]) g[a][b][0]=g[b][a][0]=c; if(c>g[a][b][1]) g[a][b][1]=g[b][a][1]=c; } prim(); bool flag=false; if(~amin&&~amax) for(int i=0; !flag&&i<30; ++i) if(amin<=f[i]&&amax>=f[i]) flag=true; puts(flag?"Yes":"No"); }}
最后我想说,上机愈少,期末临近,且练且珍惜。
- 第五次上机赛解题报告及标程
- 第五次练习赛解题报告及标程
- 第五次上机报告
- 第五次上机报告
- 第五次上机报告
- 第五次上机报告
- 第五次上机报告
- 第五次上机报告
- 第五次上机报告
- 第五次上机报告
- 第五次上机报告
- 北京航空航天大学2014第五次上机解题报告
- 第一次上机赛解题报告及标程
- 第二次上机赛解题报告及标程
- 期末上机赛解题报告及标程
- 第四次练习赛解题报告及标程
- 第六次练习赛解题报告及标程
- 第七次练习赛解题报告及标程
- 解惑 getHibernateSession().createCriteria(*).add(Restrictions.in(*)).list()
- redis的使用
- PHP扩展库的详细清单概览
- 不经常用 居然会忘记 语法什么的!! switch… case 语句的用法
- 差分约束-zoj-2770
- 第五次上机赛解题报告及标程
- Eclipse启动时报需要安装"Java SE 6 Runtime"致无法启动解决方案
- java中setOpaque()用法
- Java字符串处理的几个常用方法
- zabbix 安装(自己实践)
- UVA 10306 e-Coins
- 平板彩电寿数须达7年 国产巨子:不惧“经用”检测
- 爬虫:BeautifulSoup
- VM packet flow with neutron-lbaas-agent