8.11 暑假集训——网络流篇
来源:互联网 发布:淘宝名字怎么改昵称 编辑:程序博客网 时间:2024/05/16 10:56
第一次接触网络流,还不习惯用这种很大块而且不知道内部原理的“模板”,熟悉花了挺长时间,勉强算是会用了吧
对最大流,最省费用最大流的意义还需要加深理解,可以多复习一下最后一题,然后,刷题–
前两道是模板题
Flow problem
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <algorithm>using namespace std;#define type int //type类型可以是long long,int,double#define maxn 25 //点数#define maxm 2005 //边数,注意大于最小边数的两倍#define INF 1e8 //1e8,1e9都可int n,m;int s, t;struct Edge { int from, to, next; type cap, flow; void get (int u, int a, int b, type c, type d) { from = u; to = a; next = b; cap = c; flow = d; }}edge[maxm];int tol;int head[maxn];int gap[maxn], dep[maxn], pre[maxn], cur[maxn];void init () { tol = 0; memset (head, -1, sizeof head);}void add_edge (int u, int v, type w, type rw=0) { //模板加边 edge[tol].get(u, v,head[u],w,0);head[u]=tol++; edge[tol].get(v, u,head[v],rw,0);head[v]=tol++;}type sap (int start, int eend, int N) { //sap求最大流 memset (gap, 0, sizeof gap); memset (dep, 0, sizeof dep); memcpy (cur, head, sizeof head); int u = start; pre[u] = -1; gap[0] = N; type ans = 0; while (dep[start] < N) { if (u == eend) { type Min = INF; for (int i = pre[u]; 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[u]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = pre[v] = i; break; } } if (flag) { u = v; continue; } int Min = N; for (int i = head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]]) return ans; dep[u] = Min+1; gap[dep[u]]++; if (u != start) u = edge[pre[u]^1].to; } return ans;}int main(){ int tt; //这里的案例数注意不能用习惯的t,会隐藏全局变量 int cas=1; scanf("%d",&tt); while(tt--){ init(); //每次初始化 cin>>n>>m; for(int i=0;i<m;i++){ int u,v,w; cin>>u>>v>>w; add_edge(u,v,w); //调用模板一 } s=1,t=n; //要给全局变量s,t,n赋值 int ans=sap(1,n,n); //调用二 printf("Case %d: %d\n",cas++,ans); } return 0;}
Drainage Ditches
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <algorithm>using namespace std;const int maxn=405;const int maxm=405;const int INF=2e9+2e6;#define type intint n;int s, t;struct Edge { int from, to, next; type cap, flow; void get (int u, int a, int b, type c, type d) { from = u; to = a; next = b; cap = c; flow = d; }}edge[maxm];int tol;int head[maxn];int gap[maxn], dep[maxn], pre[maxn], cur[maxn];void init () { tol = 0; memset (head, -1, sizeof head);}void add_edge (int u, int v, type w, type rw=0) { //cout << u << " " << v << " " << w << endl; edge[tol].get(u, v,head[u],w,0);head[u]=tol++; edge[tol].get(v, u,head[v],rw,0);head[v]=tol++;}type sap (int start, int end, int N) { memset (gap, 0, sizeof gap); memset (dep, 0, sizeof dep); memcpy (cur, head, sizeof head); int u = start; pre[u] = -1; gap[0] = N; type ans = 0; while (dep[start] < N) { if (u == end) { type Min = INF; for (int i = pre[u]; 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[u]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = pre[v] = i; break; } } if (flag) { u = v; continue; } int Min = N; for (int i = head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]]) return ans; dep[u] = Min+1; gap[dep[u]]++; if (u != start) u = edge[pre[u]^1].to; } return ans;}int main(){ //主体 int m; while(~scanf("%d%d",&m,&n)){ init(); for(int i=0;i<m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); } s=1,t=n; int ans=sap(1,n,n); printf("%d\n",ans); } return 0;}
Admiral
题意: 有n个点m条边,求从1到n的不相交,且费用最小的两条路,输出最小和费用
思路: 不相交 ——> 拆除了1,n的所有点,拆出的边限流1
两条路 ——> 拆1,n点,限流2
费用最小——> 最小费用最大流
剩下的套模板就好啦~
#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <string>#include <cmath>#include <algorithm>using namespace std;const int maxm=50010;const int maxn=2005;const int INF=1e9;#define type intint s, t;struct node { int u, v, next; type cap, flow, cost;}edge[maxm];int head[maxn], cnt;int pre[maxn];type dis[maxn];bool vis[maxn];int N;void init () { memset (head, -1, sizeof head); cnt = 0;}void add_edge (int u, int v, type cap, type cost) { edge[cnt].u = u, edge[cnt].v = v, edge[cnt].cap = cap, edge[cnt].flow = 0; edge[cnt].cost = cost, edge[cnt].next = head[u], head[u] = cnt++; edge[cnt].u = v, edge[cnt].v = u, edge[cnt].cap = 0, edge[cnt].flow = 0; edge[cnt].cost = -cost, edge[cnt].next = head[v], head[v] = cnt++;}bool spfa (int s, int t) { queue <int> q; for (int i = 0; i <= N; i++) { dis[i] = INF; vis[i] = 0; pre[i] = -1; } dis[s] = 0; vis[s] = 1; q.push (s); while (!q.empty ()) { int u = q.front (); q.pop (); vis[u] = 0; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; 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] = 1; q.push (v); } } } } if (pre[t] == -1) return 0; else return 1;}int MCMF (int s, int t, type &cost) { type flow = 0; cost = 0; while (spfa (s, t)) { type Min = INF; for (int i = pre[t]; i != -1; i = pre[edge[i^1].v]) { 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].v]) { edge[i].flow += Min; edge[i^1].flow -= Min; cost += edge[i].cost*Min; } flow += Min; } return flow;}int main(){ int m; while(~scanf("%d%d",&N,&m)){ init(); for(int i=0;i<m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add_edge(u+N,v,1,w); //想想为什么是u+N } s=1,t=2*N; add_edge(1,1+N,2,0); //拆1,n点 add_edge(N,2*N,2,0); for(int i=2;i<=N-1;i++){ add_edge(i,i+N,1,0); //拆其他点 } int cost; N=2*N; //注意全局变量N的含义,细节 int flow=MCMF(1,N,cost); printf("%d\n",cost); } return 0;}
Going Home
题意: 给一个N*M的矩阵,矩阵中m与h的个数相同,m与h之间的距离为横纵方向相差的格子数之和,输出给每个m匹配一个h后,最小的距离之和 (m可以穿过h所在的格子,N,M,h的个数都<=100)
思路: 显然的二分匹配,在每个m与h之间加边,费用为距离差
建立一超级源点,超级汇点,与每个m或h的边费用为1,套最小费用最大流的模板
#include <iostream>#include <cstdio>#include <string>#include <algorithm>#include <cmath>#include <cstring>#include <vector>#include <queue>using namespace std;const int INF=1<<29;const int maxn=610;const int maxm=30010;#define type intint s, t;struct node { int u, v, next; type cap, flow, cost;}edge[maxm];int head[maxn], cnt;int pre[maxn];type dis[maxn];bool vis[maxn];int N;void init () { memset (head, -1, sizeof head); cnt = 0;}void add_edge (int u, int v, type cap, type cost) { edge[cnt].u = u, edge[cnt].v = v, edge[cnt].cap = cap, edge[cnt].flow = 0; edge[cnt].cost = cost, edge[cnt].next = head[u], head[u] = cnt++; edge[cnt].u = v, edge[cnt].v = u, edge[cnt].cap = 0, edge[cnt].flow = 0; edge[cnt].cost = -cost, edge[cnt].next = head[v], head[v] = cnt++;}bool spfa (int s, int t) { queue <int> q; for (int i = 0; i < N; i++) { dis[i] = INF; vis[i] = 0; pre[i] = -1; } dis[s] = 0; vis[s] = 1; q.push (s); while (!q.empty ()) { int u = q.front (); q.pop (); vis[u] = 0; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; 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] = 1; q.push (v); } } } } if (pre[t] == -1) return 0; else return 1;}int MCMF (int s, int t, type &cost) { type flow = 0; cost = 0; while (spfa (s, t)) { type Min = INF; for (int i = pre[t]; i != -1; i = pre[edge[i^1].v]) { 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].v]) { edge[i].flow += Min; edge[i^1].flow -= Min; cost += edge[i].cost*Min; } flow += Min; } return flow;}struct Node{ int x,y;};vector<Node> man,house;int main(){ int nn,m; while(~scanf("%d%d",&nn,&m)&&nn){ init(); char c[110]; man.clear(); //用途理清 house.clear(); for(int i=0;i<nn;i++){ scanf("%s",c); for(int j=0;j<m;j++) if(c[j]=='H') house.push_back(Node{i,j}); else if(c[j]=='m') man.push_back(Node{i,j}); } int tot=house.size(); s=0,t=2*tot+1; N=2*tot+2; //每次总点数这边都很容易理错…… 多理几遍 for(int i=0;i<tot;i++){ add_edge(0,i+1,1,0); //给每个man连超级源点 for(int j=0;j<tot;j++) add_edge(i+1,j+1+tot,1,abs(man[i].x-house[j].x)+abs(man[i].y-house[j].y)); //每个man和house连边 add_edge(i+1+tot,2*tot+1,1,0); //给每个house连超级汇点 } int cost; MCMF(0,2*tot+1,cost); //套模板 printf("%d\n",cost); } return 0;}
啊这是我WA了>20次,debug两个小时,最后还是觉得一开始代码没问题的题 ~嗷
还是网络流题目做的不熟,代码写的不够优美,姿势不太标准吧……
Delivery Bears*********
题意: 有x只熊,从带费用网络流图的点1走到n,要求每只熊背的重量相同,求n点能接收到的最大总重量(每只熊背的重量*x)
思路: 一开始想到了二分,但卡在怎么检查mid的值上,后来还是学长给了思路。
将每条路的权值除以mid,就得出每只熊背mid重量的物品时,每条路能通过的最多的熊的数量,源点和汇点拆成权为x的边,然后最大流跑一遍,判断一下是否ans==x即可
代码还是要好好理一下啊
#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <cmath>#include <iomanip>#include <algorithm>using namespace std;#define type intconst int INF=1<<29;const int maxn=600;const int maxm=20010;int n,m;int s, t;struct Edge { int from, to, next; type cap, flow; void get (int u, int a, int b, type c, type d) { from = u; to = a; next = b; cap = c; flow = d; }}edge[maxm];int tol;int head[maxn];int gap[maxn], dep[maxn], pre[maxn], cur[maxn];void init () { tol = 0; memset (head, -1, sizeof head);}void add_edge (int u, int v, type w, type rw=0) { edge[tol].get(u, v,head[u],w,0);head[u]=tol++; edge[tol].get(v, u,head[v],rw,0);head[v]=tol++;}type sap (int start, int eend, int N) { memset (gap, 0, sizeof gap); memset (dep, 0, sizeof dep); memcpy (cur, head, sizeof head); int u = start; pre[u] = -1; gap[0] = N; type ans = 0; while (dep[start] < N) { if (u == eend) { type Min = INF; for (int i = pre[u]; 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[u]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = pre[v] = i; break; } } if (flag) { u = v; continue; } int Min = N; for (int i = head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]]) return ans; dep[u] = Min+1; gap[dep[u]]++; if (u != start) u = edge[pre[u]^1].to; } return ans;}struct rese{ int u,v; int w;}res[maxm];int x;bool check( double mid){ init(); for(int i=0;i<m;i++) add_edge(res[i].u,res[i].v,min((res[i].w/mid),1.0*x)); //注意min函数里面比较的类型应该一致 add_edge(0,1,x); add_edge(n-2,n-1,x); int ans=sap(0,n-1,n); if(ans==x) return true; else return false;}int main(){ //论如何将代码写的更加优美== scanf("%d%d%d",&n,&m,&x); init(); for(int i=0;i<m;i++){ scanf("%d%d%d",&res[i].u,&res[i].v,&res[i].w); } n+=2; //最后错原来在这里…… n是包括超级源点和汇点的总点数,之前忘了+2,check函数中也没有注意噗。。 double l=0; double r=1e9; double mid,ans=0; for(int i=0;i<100;i++){ //用这样的循环会比eps更加精确 mid=(r+l)/2; if(check(mid)) l=mid,ans=mid; else r=mid; } printf("%.10f\n",ans*x); return 0;}
最后两题是紫书上的原题,重点复习最后一题
A Plug of Unix
题意: 有n个设备,m个插座,k个转换器,转换器可以叠加使用且数量无限(开始没审清题意噗。。),求最少有多少个设备无法充电
思路: 建立一个超级源点与汇点,将所有的插头插座种类都加进图中
若是设备的插头,则与超级源点连一条上限为1的边
若是插座,则与超级汇点连一条上限为1的边
是转换器x->y,则在x与y之间连一条上限无穷大的有向边
#include <iostream>#include <cstring>#include <cstdio>#include <string>#include <cstdlib>#include <cmath>#include <map>#include <vector>#include <algorithm>using namespace std;const int INF=1e9;const int maxn=1010;const int maxm=10000;#define type intint n;int s, t;struct Edge { int from, to, next; type cap, flow; void get (int u, int a, int b, type c, type d) { from = u; to = a; next = b; cap = c; flow = d; }}edge[maxm];int tol;int head[maxn];int gap[maxn], dep[maxn], pre[maxn], cur[maxn];void init () { tol = 0; memset (head, -1, sizeof head);}void add_edge (int u, int v, type w, type rw=0) { //cout << u << " " << v << " " << w << endl; edge[tol].get(u, v,head[u],w,0);head[u]=tol++; edge[tol].get(v, u,head[v],rw,0);head[v]=tol++;}type sap (int start, int eend, int N) { memset (gap, 0, sizeof gap); memset (dep, 0, sizeof dep); memcpy (cur, head, sizeof head); int u = start; pre[u] = -1; gap[0] = N; type ans = 0; while (dep[start] < N) { if (u == eend) { type Min = INF; for (int i = pre[u]; 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[u]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = pre[v] = i; break; } } if (flag) { u = v; continue; } int Min = N; for (int i = head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]]) return ans; dep[u] = Min+1; gap[dep[u]]++; if (u != start) u = edge[pre[u]^1].to; } return ans;}map<string,int> mark; //给不同种的插头插座编号int ID(string name){ if(mark.count(name)) return mark[name]; else{ mark[name]=n++; //n在这里计数,理解含义 return mark[name]; }}int main(){ int tt; scanf("%d",&tt); while(tt--){ init(); mark.clear(); n=1; int N,M; scanf("%d",&M); s=0,t=1000; vector<int> vec; for(int i=0;i<M;i++){ //设备 string name; cin>>name; int id=ID(name); vec.push_back(id); } scanf("%d",&N); for(int i=0;i<N;i++){ //插座 string name,plug; cin>>name>>plug; int id=ID(plug); add_edge(0,id,1); } int m; scanf("%d",&m); for(int i=0;i<m;i++){ //转换器 string a,b; cin>>a>>b; int aa=ID(a); int bb=ID(b); add_edge(aa,bb,INF); } for(int i=0;i<vec.size();i++) //注意这个放置的顺序==,得放在转换器读完之后== add_edge(vec[i],n,1); int ans=sap(0,n,n+1); printf("%d\n",N-ans); if(tt) printf("\n"); } return 0;}
哈哈哈哈终于到了最后一题
Matrix decompressing***************
题意: 一个R*C数阵, 已知前i行之和R[i](1<=i<=R)和前j列之和C[j](1<=j<=C),输出一个满足条件的矩阵 (1<=R,C,矩阵中每个数<=20)
思路:
这个思路很神奇,将题目化作二分匹配来做
可以求解出每行每列的数字之和,R’[i],C’[j]
让矩阵中每个数都减一,则每一行的值减C(R’[i]-C),每一列的值减R (C’[j]-R)
建立超级源点和汇点,超级源点与代表行的点相连,上限为R’[i]-C,超级汇点与代表列的点相连,上限为C’[j]-R
代表行的点与每个代表列的点相连,上限为19
求一遍最大流,满流则有解,解为边最后的流量
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <algorithm>using namespace std;// 好巧妙的一题 *********#define type intconst int INF=1e9;const int maxn=200;const int maxm=1050;int n;int s, t;struct Edge { int from, to, next; type cap, flow; void get (int u, int a, int b, type c, type d) { from = u; to = a; next = b; cap = c; flow = d; }}edge[maxm];int tol;int head[maxn];int gap[maxn], dep[maxn], pre[maxn], cur[maxn];void init () { tol = 0; memset (head, -1, sizeof head);}void add_edge (int u, int v, type w, type rw=0) { //cout << u << " " << v << " " << w << endl; edge[tol].get(u, v,head[u],w,0);head[u]=tol++; edge[tol].get(v, u,head[v],rw,0);head[v]=tol++;}type sap (int start, int eend, int N) { memset (gap, 0, sizeof gap); memset (dep, 0, sizeof dep); memcpy (cur, head, sizeof head); int u = start; pre[u] = -1; gap[0] = N; type ans = 0; while (dep[start] < N) { if (u == eend) { type Min = INF; for (int i = pre[u]; 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[u]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = pre[v] = i; break; } } if (flag) { u = v; continue; } int Min = N; for (int i = head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]]) return ans; dep[u] = Min+1; gap[dep[u]]++; if (u != start) u = edge[pre[u]^1].to; } return ans;}int row[25],cow[25];int main(){ //重点 int tt;scanf("%d",&tt); int cas=1; while(tt--){ init(); int r,c; scanf("%d%d",&r,&c); //读入 for(int i=0;i<r;i++) scanf("%d",&row[i]); for(int i=0;i<c;i++) scanf("%d",&cow[i]); //处理出每一行每一列的和 for(int i=r-1;i>0;i--) row[i]-=row[i-1]; for(int j=c-1;j>0;j--) cow[j]-=cow[j-1]; s=0,t=r+c+1; n=r+c+2; //超级源点,超级汇点加边 for(int i=0;i<r;i++) add_edge(0,i+1,row[i]-c); for(int j=0;j<c;j++) add_edge(r+j+1,r+c+1,cow[j]-r); //行的点与列的点之间加边,注意加边顺序 for(int i=0;i<r;i++) for(int j=c-1;j>=0;j--) //这里放入边的顺序会影响最后的输出顺序 add_edge(i+1,r+j+1,19); sap(0,r+c+1,r+c+2); printf("Matrix %d\n",cas++); for(int i=1;i<=r;i++){ for(int j=head[i];edge[j].next!=-1;j=edge[j].next){ //head[u]存以u为起点的所以边的值,注意最后一条是到超级源点的逆序边 printf("%d",edge[j].flow+1); if(edge[edge[j].next].next!=-1) printf(" "); } printf("\n"); } } return 0;}
图论这才刚刚开始,加油吧少年~
- 8.11 暑假集训——网络流篇
- 7.21 暑假集训——动态规划篇(二)
- 8.5 暑假集训——线段树篇
- 8.7 暑假集训——树状数组篇
- 暑假集训——破壳计划
- 2016暑假集训总结——Part1
- 2016暑假集训总结——Part2
- XYNU—ACM暑假集训第一次测试
- XYNU—ACM暑假集训第二次测试
- 暑假集训-二分图,网络流,2-SAT
- 暑假集训 8.11 树结构练习——排序二叉树的中序遍历 sdutoj2128
- 暑假集训——贪心专题——F题
- 暑假集训——贪心专题——A题
- 暑假集训——贪心专题——D题
- 暑假集训——贪心专题——I题
- 暑假集训——贪心专题——E题
- 暑假集训——贪心专题——C题
- ACM 学习心得 ——2014年ACM暑假集训有感
- 狄克斯特拉算法,解决加权最短路径问题--python实现
- Thread Join()的用法
- MPEG-DASH简介
- 带你了解android的IPC机制
- Hdu 1796 How many integers can you find【二进制枚举容斥原理入门】
- 8.11 暑假集训——网络流篇
- Worm(毛毛虫)HDU2151
- 5-29 修理牧场 (25分)(数组模拟,没有用到优先队列)**代码是我在网上找到的
- zabbix服务器端部署 for CentOS7
- 自定义权限模块2——自定义tld标签
- 电子设计竞赛指导总结
- Hibernate学习笔记(一)
- stm32成长记之LED呼吸灯
- websocket:如何建立在同一台client和同一台server创建多个连接