最近一段时间再搞网络流,今天终于搞完了!!!!QAQ,好累呀。

首先是关于网络流的基础知识,这部分东西有点多,就不在这里说了,给几个有用的资源。

先推荐一下建图的博客:链式向前星,静态链表和邻接矩阵建图

之后就是网络流入门的知识,可以看刘汝佳的紫书里面的知识和这几个博客

网络流--最大流          数据结构与算法分析 - 网络流入门(Network Flow)

知道一些基础知识之后,就可以去用比较简单的增广路算法去做几道水题。

hdu1532最大流模板题   hdu3549——最大流模板题,这两个题不给代码了,都很简单。

我们现在估计应该都知道最大流问题了,我在这里给出基于EK算法实现的最大流算法,其实就是BFS。

抛代码模板

先给出基于邻接表的实现(来源刘汝佳紫书

struct Edge{int from,to,cap,flow;Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};struct EdmondsKarp{int n,m;vector<Edge>edges;//边数的两倍vector<int>G[maxn];//邻接表,G[i][j]表示结点i的第j条边在e数组中的序号int a[maxn];//当起点到i的可改进量int p[maxn];//最短路树上p的入弧编号void init(int n){for(int i=0;i<n;i++)G[i].clear();edges.clear();}void AddEdge(int from,int to,int cap){edges.push_back(Edge(from,to,cap,0));edges.push_back(Edge(to,from,0,0));//反向弧m=edges.size();G[from].push_back(m-2);G[to].push_back(m-1);}int Maxflow(int s,int t){int flow=0;for(;;){memset(a,0,sizeof(a));queue<int>Q;Q.push(s);a[s]=INF;while(!Q.empty()){int x=Q.front();Q.pop();for(int i=0;i<G[x].size();i++){Edge &e=edges[G[x][i]];if(!a[e.to]&&e.cap>e.flow){p[e.to]=G[x][i];a[e.to]=min(a[x],e.cap-e.flow);Q.push(e.to);}}if(a[t])break;}if(!a[t])break;for(int u=t;u!=s;u=edges[p[u]].from){edges[p[u]].flow+=a[t];edges[p[u]^1].flow-=a[t];}flow+=a[t];}return flow;}
}EK;

然后是基于邻接矩阵的实现,比较简单

#include <iostream>
#include <queue>
#include<string.h>
using namespace std;
#define arraysize 201
int maxData = 0x7fffffff;
int capacity[arraysize][arraysize]; //记录残留网络的容量
int flow[arraysize];                //标记从源点到当前节点实际还剩多少流量可用
int pre[arraysize];                 //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
int n,m;
queue<int> myqueue;
int BFS(int src,int des)
{int i,j;while(!myqueue.empty())       //队列清空myqueue.pop();for(i=1;i<m+1;++i){pre[i]=-1;}pre[src]=0;flow[src]= maxData;myqueue.push(src);while(!myqueue.empty()){int index = myqueue.front();myqueue.pop();if(index == des)            //找到了增广路径break;for(i=1;i<m+1;++i){if(i!=src && capacity[index][i]>0 && pre[i]==-1){pre[i] = index; //记录前驱flow[i] = min(capacity[index][i],flow[index]);   //关键:迭代的找到增量myqueue.push(i);}}}if(pre[des]==-1)      //残留图中不再存在增广路径return -1;elsereturn flow[des];
}
int maxFlow(int src,int des)
{int increasement= 0;int sumflow = 0;while((increasement=BFS(src,des))!=-1){int k = des;          //利用前驱寻找路径while(k!=src){int last = pre[k];capacity[last][k] -= increasement; //改变正向边的容量capacity[k][last] += increasement; //改变反向边的容量k = last;}sumflow += increasement;}return sumflow;
}
int main()
{int i,j;int start,end,ci;while(cin>>n>>m){memset(capacity,0,sizeof(capacity));memset(flow,0,sizeof(flow));for(i=0;i<n;++i){cin>>start>>end>>ci;if(start == end)               //考虑起点终点相同的情况continue;capacity[start][end] +=ci;     //此处注意可能出现多条同一起点终点的情况}cout<<maxFlow(1,m)<<endl;}return 0;
}

知道最大流之后,就可以学一下最小割最大流定理,其实就是最大流的另一种表现形式,换了一种问的方式,结果一样。

最小割是指把两个点割开所花费的最低成本,定理就是最小割等于最大流。

至于证明可以去网上搜一下。

然后讲一下最大流进阶的算法(Dinic算法和SAP算法以及优化的ISAP算法)

Dinic算法的讲解可以看这篇文章:Dinic算法(研究总结,网络流)

SAP算法和ISAP算法的讲解可以看这个:网络流-最大流问题 ISAP 算法解释

总的最大流常用算法的时间复杂度为:ISAP>SAP>Dinic>EK≈FF

下面抛代码

基于邻接表的Dinic

#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1000 + 10;
const int INF = 0x3f3f3f3f;
struct Edge
{int from, to, cap, flow;Edge(int u, int v, int c, int f) : from(u), to(v), cap(c), flow(f) {}
};
struct Dinic
{int n, m, s, t;//结点数,边数,(包括反向弧),源点编号和汇点编号 vector<int> G[maxn];//边表,edges[e]与edges[e^1]互为反向弧 vector<Edge> edges;//邻接表,G[i][j]表示结点 i 的第 j 条边在 e 数组的序号 bool vis[maxn];//BFS使用 int d[maxn]; //从起点到 i 的距离 int cur[maxn];//当前弧下标 void init(int n){this->n = n;for(int i = 0; i <= n; i++)G[i].clear();edges.clear();}void AddEdge(int from, int to, int cap){edges.push_back(Edge(from, to, cap, 0));edges.push_back(Edge(to, from, 0, 0));m = edges.size();G[from].push_back(m-2);G[to].push_back(m-1);}bool bfs(){memset(vis, false, sizeof(vis));queue<int> Q;d[s] = 0;Q.push(s);vis[s] = true;while(!Q.empty()){int x = Q.front();Q.pop();for(int i = 0; i < G[x].size(); i++){Edge& e = edges[G[x][i]];if(!vis[e.to] && e.cap>e.flow)//只考虑残量网络中的弧 {d[e.to] = d[x] + 1;Q.push(e.to);vis[e.to] = true;}}}return vis[t];}int dfs(int x, int a){if(x==t || a==0)return a;int f, flow = 0;for(int& i = cur[x]; i < G[x].size(); i++)//当前弧优化 {Edge& e = edges[G[x][i]];if(d[e.to]==d[x]+1 && (f=dfs(e.to, min(a, e.cap-e.flow)))>0){e.flow += f;edges[G[x][i]^1].flow -= f;flow += f;a -= f;if(a == 0)break;}}return flow;}int max_flow(int s, int t){this->s = s;this->t = t;int flow = 0;while(bfs()){memset(cur, 0, sizeof(cur));flow += dfs(s, INF);}return flow;}
}D;
int main(){int n,m;while(scanf("%d%d", &n, &m) != EOF){D.init(n+1);int u, v, w;for(int i = 0; i < m; i++){scanf("%d%d%d", &u, &v, &w);D.AddEdge(u, v, w);D.AddEdge(v, u, 0);}printf("%d\n", D.max_flow(1,n));}return 0;
}

基于邻接矩阵的Dinic算法

#include <bits/stdc++.h>
using namespace std;
const int maxn=450;
int n,m,dis[maxn],E[maxn][maxn];
bool bfs(int s)
{memset(dis,-1,sizeof(dis));queue<int> q;dis[s]=0;while(!q.empty()){int now=q.front();q.pop();for(int i = 1;i<=n;i++){if(dis[i]<0&&E[now][i]>0){dis[i]=dis[now]+1;q.push(i); }} }if(dis[n]>0) return true;else return false;
}
int Find(int x,int low)
{int a=0;if(x==n) return low;for(int i = 1;i<=n;i++){if(E[x][i]>0&&dis[i]==dis[x]+1&&(a=Find(1,min(low,E[x][i])))){E[x][i]-=a;E[i][x]+=a;return a;}}return 0;
}
int main(int argc, char** argv) {while(cin>>n>>m){memset(E,0,sizeof(E));for(int i = 1;i<=m;i++){int u,v,w;cin>>u>>v>>w;E[u][v]+=w;}int ans=0;while(bfs(1)){int tmp;while(tmp=Find(1,INT_MAX)){ans+=tmp;}}cout<<ans<<endl;}return 0;
}

基于邻接表的ISAP算法


#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 5010;
const int MAXN_INT = (1 << 29);
struct Edge{int v, w, nxt;
};
bool isFind;
int head[MAXN];
Edge edge[MAXN];
int dis[MAXN], gap[MAXN];
int n, m, ecnt, aug, maxFlow;
void init(){ecnt = maxFlow = 0;memset(gap, 0, sizeof(gap));memset(dis, 0, sizeof(dis));memset(edge, 0, sizeof(edge));memset(head, -1, sizeof(head));gap[0] = n;
}
void addEdge(int u, int v, int w){edge[ecnt].v = v;edge[ecnt].w = w;edge[ecnt].nxt = head[u];head[u] = ecnt++;
}
void Find(int s){int dx, augc, minDis;if(s == n){isFind = true;maxFlow += aug;return;}augc = aug;minDis = n - 1;for(int i = head[i]; i + 1; i = edge[i].nxt){if(edge[i].w > 0){if(dis[s] == dis[edge[i].v] + 1){aug = min(aug, edge[i].w);Find(edge[i].v);if(dis[1] >= n) return;if(isFind){dx = i;break;}aug = augc;}minDis = min(minDis, dis[edge[i].v]);}}if(!isFind){gap[dis[s]]--;if(gap[dis[s]] == 0) dis[1] = n;dis[s] = minDis + 1;gap[dis[s]]++;}else{edge[dx].w -= aug;edge[dx ^ 1].w += aug;}
}
int main(){while(scanf("%d%d", &n, &m) != EOF){init();int u, v, w;for(int i = 0; i < m; i++){scanf("%d%d%d", &u, &v, &w);addEdge(u, v, w);addEdge(v, u, 0);}while(dis[1] < n){isFind = 0;aug = MAXN_INT;Find(1);}cout << maxFlow << endl;}return 0;
}

基于邻接矩阵的ISAP算法

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 222
#define inf 100000000+1000
int map[MAXN][MAXN];//存图
int pre[MAXN];//记录当前点的前驱
int level[MAXN];//记录距离标号
int gap[MAXN];//gap常数优化
int NV,NE;//入口参数vs源点,vt汇点
int SAP(int vs,int vt)
{memset(pre,-1,sizeof(pre));memset(level,0,sizeof(level));memset(gap,0,sizeof(gap));gap[0]=vt;int v,u=pre[vs]=vs,maxflow=0,aug=inf;while(level[vs]<vt){//寻找可行弧for(v=1;v<=vt;v++){if(map[u][v]>0&&level[u]==level[v]+1){break;}}if(v<=vt){pre[v]=u;u=v;if(v==vt){int neck=0;aug=inf;//寻找当前找到的一条路径上的最大流 , (瓶颈边)for(int i=v;i!=vs;i=pre[i]){if(aug>map[pre[i]][i]){aug=map[pre[i]][i];neck=i;}}maxflow+=aug;//更新残留网络for(int i=v;i!=vs;i=pre[i]){map[pre[i]][i]-=aug;map[i][pre[i]]+=aug;}u=vs;       //从源点开始继续搜//      u=neck;      // Dnic 多路增广优化,下次增广时,从瓶颈边(后面)开始}}else{//找不到可行弧int minlevel=vt;//寻找与当前点相连接的点中最小的距离标号for(v=1;v<=vt;v++){if(map[u][v]>0&&minlevel>level[v]){minlevel=level[v];}}gap[level[u]]--;//(更新gap数组)当前标号的数目减1;if(gap[level[u]]==0)break;//出现断层level[u]=minlevel+1;gap[level[u]]++;u=pre[u];}}return maxflow;
}int main()
{int n,m,u,v,cap;while(~scanf("%d%d",&m,&n)){memset(map,0,sizeof(map));for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&cap);map[u][v]+=cap;}printf("%d\n",SAP(1,n));}return 0;
}

下面进入另一个经典的网络流问题,最小费用最大流问题。

其实就是边多了一个权值,费用,然后在求所有的最大流里面最小的费用的最大流。

关于这个算法的知识可以参考这篇文章:网络流(六)最小费用最大流问题

也可以看紫书里面的内容,废话不多说,上大白书里面的模板

struct Edge{int from,to,cap,flow,cost;Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){}
};struct MCMF{int n,m;vector<Edge>edges;vector<int>G[maxn];int inq[maxn];//是否在队列中int d[maxn];//Bellman-Fordint p[maxn];//上一条弧int a[maxn];//可改进量void init(int n){this->n=n;for(int i=0;i<n;i++)G[i].clear();edges.clear();}void AddEdge(int from,int to,int cap,int cost){edges.push_back(Edge(from,to,cap,0,cost));edges.push_back(Edge(to,from,0,0,-cost));m=edges.size();G[from].push_back(m-2);G[to].push_back(m-1);}bool BellmanFord(int s,int t,int &flow,long long &cost){for(int i=0;i<n;i++)d[i]=INF;memset(inq,0,sizeof(inq));d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;queue<int>Q;Q.push(s);while(!Q.empty()){int u=Q.front();Q.pop();inq[u]=0;for(int i=0;i<(int)G[u].size();i++){Edge &e=edges[G[u][i]];if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){d[e.to]=d[u]+e.cost;p[e.to]=G[u][i];a[e.to]=min(a[u],e.cap-e.flow);if(!inq[e.to]){Q.push(e.to);inq[e.to]=1;}}}}if(d[t]==INF)return false;flow+=a[t];cost+=(long long)d[t]*(long long)a[t];for(int u=t;u!=s;u=edges[p[u]].from){edges[p[u]].flow+=a[t];edges[p[u]^1].flow-=a[t];}return true;}//需要保证初始网络中没有负权圈int MincostMaxflow(int s,int t,long long &cost){int flow=0;cost=0;while(BellmanFord(s,t,flow,cost));return flow;}
}MM;

其实关于最小费用最大流的求法还有两种,SPFA以及zkw最小费用流(适用于二分图)

基于SPFA的实现

struct Edge{int to,next,cap,flow,cost;
}edge[MAXM];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int N;//节点总个数,节点编号从0~N-1
void init(int n){N=n;tol=0;memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost){edge[tol].to=v;edge[tol].cap=cap;edge[tol].cost=cost;edge[tol].flow=0;edge[tol].next=head[u];head[u]=tol++;edge[tol].to=u;edge[tol].cap=0;edge[tol].cost=-cost;edge[tol].flow=0;edge[tol].next=head[v];head[v]=tol++;
}
bool spfa(int s,int t){queue<int>q;for(int i=0;i<N;i++){dis[i]=INF;vis[i]=false;pre[i]=-1;}dis[s]=0;vis[s]=true;q.push(s);while(!q.empty()){int u=q.front();q.pop();vis[u]=false;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){dis[v]=dis[u]+edge[i].cost;pre[v]=i;if(!vis[v]){vis[v]=true;q.push(v);}}}}if(pre[t]==-1)return false;else return true;
}
//返回的是最大流,cost存的是最小费用
int minCostMaxflow(int s,int t,int &cost){int flow=0;cost=0;while(spfa(s,t)){int Min=INF;for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){if(Min>edge[i].cap-edge[i].flow)Min=edge[i].cap-edge[i].flow;}for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){edge[i].flow+=Min;edge[i^1].flow-=Min;cost+=edge[i].cost*Min;}flow+=Min;}return flow;
}

基于zkw费用流的实现

struct Edge{int to,next,cap,flow,cost;Edge(int _to=0,int _next=0,int _cap=0,int _flow=0,int _cost=0):to(_to),next(_next),cap(_cap),flow(_flow),cost(_cost){}
}edge[MAXM];
struct ZKW_MinCostMaxFlow{int head[MAXN],tot;int cur[MAXN];int dis[MAXN];bool vis[MAXN];int ss,tt,N;//源点、汇点和点的总个数(编号是0~N-1),不需要额外赋值,调用会直接赋值int min_cost,max_flow;void init(){tot=0;memset(head,-1,sizeof(head));}void addedge(int u,int v,int cap,int cost){edge[tot]=Edge(v,head[u],cap,0,cost);head[u]=tot++;edge[tot]=Edge(u,head[v],0,0,-cost);head[v]=tot++;}int aug(int u,int flow){if(u==tt)return flow;vis[u]=true;for(int i=cur[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].cap>edge[i].flow&&!vis[v]&&dis[u]==dis[v]+edge[i].cost){int tmp=aug(v,min(flow,edge[i].cap-edge[i].flow));edge[i].flow+=tmp;edge[i^1].flow-=tmp;cur[u]=i;if(tmp)return tmp;}}return 0;}bool modify_label(){int d=INF;for(int u=0;u<N;u++)if(vis[u])for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].cap>edge[i].flow&&!vis[v])d=min(d,dis[v]+edge[i].cost-dis[u]);}if(d==INF)return false;for(int i=0;i<N;i++)if(vis[i]){vis[i]=false;dis[i]+=d;}return true;}/*直接调用获取最小费用和最大流输入:start-源点,end-汇点,n-点的总个数(编号从0开始)返回值:pair<int,int>第一个是最小费用,第二个是最大流*/pair<int,int> mincostmaxflow(int start,int end,int n){ss=start,tt=end,N=n;min_cost=max_flow=0;for(int i=0;i<n;i++)dis[i]=0;while(1){for(int i=0;i<n;i++)cur[i]=head[i];while(1){for(int i=0;i<n;i++)vis[i]=false;int tmp=aug(ss,INF);if(tmp==0)break;max_flow+=tmp;min_cost+=tmp*dis[ss];}if(!modify_label())break;}return make_pair(min_cost,max_flow);}
};

下面的才是真正的重点——建模和模型的变换

资料:

最详细(也可能现在不是了)网络流建模基础

算法竞赛入门经典——训练指南(简称大白书,真的是经典,有的你第一次看看不懂,等真正做题时才能意识到)

主要内容:

建模的方法和技巧。以下来自白书

方法:

1.多源多汇问题:有多个源点多个汇点,构造一个超级汇点和超级源点,超级汇点和汇点相连,容量为无穷大,同理汇点也一样

2.结点容量:拆点,把结点拆成两个,一个入点,一个出点,并且建边,容量为结点的容量。

3.无源无汇的有容量下界的网络的最大流:详见白书,自己也不是很清楚,通过一道题懂得,在kuangbin带你飞专题里面。

4.费用和流量平方成正比的最小流:拆边法,详见大白书。

技巧:

1.二分图带权最大独立集。

2.公平分配问题。

3.区间k覆盖问题

4.最大闭合子图。

5.最大密度子图

以上的内容都是来源于白书,我感觉都是一些很概念性的东西,如果没做题的话就不能体会,所以还是要多做题!!!!

好了,下面就是牛逼的部分,附上kuangbin带你飞网络流专题的习题和详解。


kuangbin带你飞网络流专题
POJ3436——建图和最大流路径记录 题解
POJ3281——巧妙建图!! 题解
POJ1087——建图+建图+最大匹配(最大流) 题解
poj2195——最小费用最大流模板题 题解
POJ2516——分治+最小费用最大流 题解
POJ1459——最大流模板题(EK,多方法) 题解
hdu4280——最大流基础题 题解
hdu4292——建模题(EK会超时) 题解
hdu4289——最大流最小割+拆点 题解
UVA10480——最大流最小割(路径输出)板子题 题解
hdu2732——建图最大流+拆点 题解
hdu3338——建图+最大流 题解
hdu3081——最大流(二分图)+并查集(floyd)+二分 题解
hdu3416——最短路+最大流 题解

网络流入门——算法模板,习题和解析相关推荐

  1. 基础算法-模板习题一

    文章目录 快速排序模版 快速排序习题--求数组中第 k 小 的数 归并排序模板 归并排序习题--求逆序对的个数问题 二分习题--求数的三次方根 一维前缀和习题--求前缀和 二维前缀和习题--求子矩阵的 ...

  2. 网络流Dinic算法模板 POJ1273

    这就是以后我的板子啦~~~ #include <queue> #include <cstdio> #include <cstring> #include <a ...

  3. 网络流-SAP算法模板

    node 表示当前讨论到的节点: flow 表示该节点被传入/要传出的流量:s, t, ver 分别是起点,终点,节点总数: SAP 函数返回增广路成功增大的流量: dlt 是当前已传出的流量: c ...

  4. 【算法笔记】莫比乌斯反演(包含定理,两种形式的证明及入门经典模板)

    整理的算法模板合集: ACM模板 目录 一.莫比乌斯反演 二.几个概念和定理 三.两种形式的莫比乌斯反演证明 四.POJ 3904 Sky Code(入门例题) 一.莫比乌斯反演 学习笔记,我是看这个 ...

  5. java课后习题七解析_《Java基础入门》_课后习题解析.doc

    <Java基础入门>_课后习题解析 <Java基础入门>课后习题 Java开发入门 一.填空题 1.Java的三大体系分别是_JavaSE_____._JavaEE_____. ...

  6. KMP算法模板与解析

    全部数据结构.算法及应用课内模板请点击:https://blog.csdn.net/weixin_44077863/article/details/101691360 将KMP算法,就要先讲讲它是用来 ...

  7. 豆瓣评分 9.4 的算法巨著,这本书带无数读者入门算法

    说到算法巨著,你可能想到的是<算法导论>这本经典.但在入门算法时,还有一本与之比肩的巨著,不得不提,它就是<算法(第4版)>. 这本豆瓣评分 9.4 的算法巨著,可谓是算法经典 ...

  8. Python 算法模板库,Pythonista 找工作利器

    来源:Github-dashidhy https://github.com/dashidhy/algorithm-pattern-python [导语]程序员找工作,刷算法题是必不可少的一步,这里给广 ...

  9. 计算机考研数据结构算法模板

    计算机考研数据结构算法模板 前言 临近考研,想给考研党们分享一些比较通用的算法模板,让复习更高效一点.如果备考时间足够长,备考人应该有大量时间刷大量习题,会有自己总结的算法模板,笔者文章参考了王道考研 ...

最新文章

  1. httpTomcat
  2. 看得“深”、看得“清” —— 深度学习在图像超清化的应用
  3. CentOS7安装Nagios并配置出图详解
  4. Tableau必知必会之学做 饼图 和 折线图 的组合图表
  5. 《研磨设计模式》chap18 状态模式state(4)例子
  6. 花旗linux 内核 如何调试,揭秘首个运行在Linux平台的核心银行系统
  7. Java基础部分快速复习(以前复习的时候放在自己的新浪博客上)
  8. sql server 2005 T-SQL BULK INSERT (Transact-SQL)
  9. json在html中怎么遍历list,怎么对Json对象进行遍历呢?
  10. SBuild 0.2.0 发布,基于 Scala 的构建系统
  11. 别人都说我老公的字写的不错,大家帮我看看这字行不?
  12. java http 面试题_Java面试高级篇—说说TCP,UDP和socket,Http之间联系和区别面试题12期...
  13. WSL之Emacs中文乱码解决
  14. 一次新生代民工工友切磋经历
  15. 【转】VNode节点
  16. apache如何加载系统环境变量_游学电子:windows10系统如何用cmd指令设置环境变量...
  17. layui select 默认选中
  18. plex插件显示无服务器,Plex插件
  19. 关于NB-IoT,这四十个问题经典回答
  20. 第四章:Django特级篇

热门文章

  1. DataGridView使用bindingNavigator实现分页功能(应用存储过程)
  2. LeetCode 2017. Grid Game【前缀和/数组】中等
  3. 运动耳机哪种佩戴方式好?佩戴稳固舒适的运动耳机
  4. html判断input的状态,HTML实现检测输入已完成功能
  5. 阿里技术四面+交叉面+HR面成功拿到offer,谁说双非本科进不了大厂?
  6. 2020-12-31小黄自学文档整理(其实是小白,因为姓黄)
  7. python 采集新闻_Python多篇新闻自动采集
  8. 百度上湖南卫视招聘 李彦宏展现舞技
  9. 定制自己的Linux 系统
  10. 今天面了个字节跳动拿35K出来的,真是砂纸擦屁股,给我露了一手啊