算法详解

等价流树正如其名,树上两点间的路径上的边权最小值为图上两点间的最小割。

Gusfield算法就是建等价流树的一种算法。设当前正在处理的集合为 \(S(|S|\ge 2)\),从 \(S\) 中任选两个点 \(x,y\),求出 \(x,y\) 间的最小割也就是最大流 \(flow\),此时在最小割树中加入一条从 \(x\) 到 \(y\),边权为 \(flow\)。在原图中去掉所有的满流边后,\(S\) 会变成两部分,一部分是在残量网络上从起点能遍历到的点,另一部分是遍历不到的点,分治下去求解即可,很容易可以发现,最多求解 \(n-1\) 次,所以得到的必然是棵树。

证明这个做法建出来的树必然满足树上路径边权最小值等于原图上两点间的最小割。

有一种不严谨的证明,因为递归出来的两边都是合法的等价流树,假设这两棵等价流树中的边权全部大于 \((s,t)\) 这条边,那么显然割掉 \((s,t)\) 代表的原图中的边集会优于割掉其它边代表的原图中的边集。即若存在 \(u,v\) 分别再 \(s,t\) 侧,\((s,t)\) 这条边的边权必然为 \(u,v\) 的最小割。至于更详细的证明可以研读2016年王文涛国集论文

例题

1.【模板】最小割树(Gomory-Hu Tree)

其实我并不觉得这是GHT的模板,它只用到了大小,并没有用到方案等其它信息。直接建出等价流树,每次询问在等价流树上找路径边权最小值即可,倍增预处理皆可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=510,M=6010,Lg=11,inf=1e9;
int n,m,head[N],hd[N],tot1=0,tot=1,id[N];
struct edge{
int v,w,nxt;
}e[M],G[M];
void add(int u,int v,int w){
e[++tot].v=v;
e[tot].nxt=head[u];
e[tot].w=w;
head[u]=tot;
}
void add1(int u,int v,int w){
G[++tot1].v=v;
G[tot1].w=w;
G[tot1].nxt=hd[u];
hd[u]=tot1;
}
namespace GHT{
int dep[N],cur[N],tmp1[N],tmp2[N];
bool bfs(int S,int T){
for(int i=1;i<=n;i++){
dep[i]=0;
}
queue<int>q;
q.push(S);
dep[S]=1;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].v,w=e[i].w;
if(w&&!dep[v]){
dep[v]=dep[u]+1;
q.push(v);
if(v==T){
return 1;
}
}
}
}
return 0;
}
int dfs(int u,int flow,int T){
if(u==T){
return flow;
}
int s=0;
for(int i=cur[u];i;i=e[i].nxt){
cur[u]=i;
int v=e[i].v,w=e[i].w;
if(w&&dep[v]==dep[u]+1){
int res=dfs(v,min(flow,w),T);
e[i].w-=res;
e[i^1].w+=res;
flow-=res;
s+=res;
}
if(!flow){
break;
}
}
if(!s){
dep[u]=0;
}
return s;
}
void init(){
for(int i=0;i<=tot;i+=2){
e[i].w+=e[i^1].w;
e[i^1].w=0;
}
}
int dinic(int S,int T){
init();
int ans=0;
while(bfs(S,T)){
memcpy(cur,head,sizeof(head));
ans+=dfs(S,inf,T);
}
return ans;
}
void build(int l,int r){
if(l>=r){
return;
}
int x=id[l],y=id[l+1];
int flow=dinic(x,y);
add1(x,y,flow);
add1(y,x,flow);
int cnt1=0,cnt2=0;
for(int i=l;i<=r;i++){
if(dep[id[i]]){
tmp1[++cnt1]=id[i];
}
else{
tmp2[++cnt2]=id[i];
}
}
for(int i=1;i<=cnt1;i++){
id[l+i-1]=tmp1[i];
}
for(int i=1;i<=cnt2;i++){
id[cnt1+i+l-1]=tmp2[i];
}
build(l,l+cnt1-1);
build(l+cnt1,r);
}
}
int f[N][Lg+5],mn[N][Lg+5],dep[N];
void make_tree(int u,int father){
f[u][0]=father;
dep[u]=dep[father]+1;
for(int i=1;i<=Lg;i++){
f[u][i]=f[f[u][i-1]][i-1];
mn[u][i]=min(mn[u][i-1],mn[f[u][i-1]][i-1]);
}
for(int i=hd[u];i;i=G[i].nxt){
int v=G[i].v,w=G[i].w;
if(v==father){
continue;
}
mn[v][0]=w;
make_tree(v,u);
}
}
int lca(int u,int v){
if(dep[u]<dep[v]){
swap(u,v);
}
int mini=inf;
for(int i=Lg;i>=0;i--){
if(dep[f[u][i]]>=dep[v]){
mini=min(mini,mn[u][i]);
u=f[u][i];
}
}
if(u==v){
return mini;
}
for(int i=Lg;i>=0;i--){
if(f[u][i]!=f[v][i]){
mini=min(mini,min(mn[u][i],mn[v][i]));
u=f[u][i],v=f[v][i];
}
}
return min(mini,min(mn[u][0],mn[v][0]));
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
memset(mn,0x3f,sizeof(mn));
read(n),read(m);
for(int i=1,u,v,w;i<=m;i++){
read(u),read(v),read(w);
add(u,v,w);
add(v,u,0);
add(v,u,w);
add(u,v,0);
}
for(int i=1;i<=n;i++){
id[i]=i;
}
GHT::build(1,n);
make_tree(1,0);
int q;
read(q);
while(q--){
int u,v;
read(u),read(v);
write_endl(lca(u,v));
}
return 0;
}

2.[ZJOI2011]最小割

也是个板题,建出等价流树,如果不连通,就每个连通块之间建一条长度为 \(0\) 的边,最后询问时在树上以每个点为起点扫一遍即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=510,M=60010,inf=1e12;
int n,m,head[N],hd[N],tot1=0,tot=1,id[N],fa[N];
struct edge{
int v,w,nxt;
}e[M],G[M];
int getfa(int x){
if(fa[x]!=x){
fa[x]=getfa(fa[x]);
}
return fa[x];
}
void merge(int u,int v){
u=getfa(u),v=getfa(v);
if(u!=v){
fa[v]=u;
}
}
void add(int u,int v,int w){
e[++tot].v=v;
e[tot].nxt=head[u];
e[tot].w=w;
head[u]=tot;
}
void add1(int u,int v,int w){
G[++tot1].v=v;
G[tot1].w=w;
G[tot1].nxt=hd[u];
hd[u]=tot1;
merge(u,v);
}
namespace GHT{
int dep[N],cur[N],tmp1[N],tmp2[N];
bool bfs(int S,int T){
for(int i=1;i<=n;i++){
dep[i]=0;
}
queue<int>q;
q.push(S);
dep[S]=1;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].v,w=e[i].w;
if(w&&!dep[v]){
dep[v]=dep[u]+1;
q.push(v);
if(v==T){
return 1;
}
}
}
}
return 0;
}
int dfs(int u,int flow,int T){
if(u==T){
return flow;
}
int s=0;
for(int i=cur[u];i;i=e[i].nxt){
cur[u]=i;
int v=e[i].v,w=e[i].w;
if(w&&dep[v]==dep[u]+1){
int res=dfs(v,min(flow,w),T);
e[i].w-=res;
e[i^1].w+=res;
flow-=res;
s+=res;
}
if(!flow){
break;
}
}
if(!s){
dep[u]=0;
}
return s;
}
void init(){
for(int i=0;i<=tot;i+=2){
e[i].w+=e[i^1].w;
e[i^1].w=0;
}
}
int dinic(int S,int T){
init();
int ans=0;
while(bfs(S,T)){
memcpy(cur,head,sizeof(head));
ans+=dfs(S,inf,T);
}
return ans;
}
void build(int l,int r){
if(l>=r){
return;
}
int x=id[l],y=id[l+1];
int flow=dinic(x,y);
add1(x,y,flow);
add1(y,x,flow);
int cnt1=0,cnt2=0;
for(int i=l;i<=r;i++){
if(dep[id[i]]){
tmp1[++cnt1]=id[i];
}
else{
tmp2[++cnt2]=id[i];
}
}
for(int i=1;i<=cnt1;i++){
id[l+i-1]=tmp1[i];
}
for(int i=1;i<=cnt2;i++){
id[cnt1+i+l-1]=tmp2[i];
}
build(l,l+cnt1-1);
build(l+cnt1,r);
}
}
void clear(){
for(int i=1;i<=n;i++){
head[i]=hd[i]=0;
id[i]=i;
fa[i]=i;
}
tot=tot1=1;
}
int ans,x;
void dfs(int u,int father,int mn){
if(mn<=x){
ans++;
}
for(int i=hd[u];i;i=G[i].nxt){
int v=G[i].v,w=G[i].w;
if(v==father){
continue;
}
dfs(v,u,min(mn,w));
}
}
void solve(){
read(n),read(m);
clear();
for(int i=1,u,v,w;i<=m;i++){
read(u),read(v),read(w);
add(u,v,w);
add(v,u,0);
add(v,u,w);
add(u,v,0);
}
GHT::build(1,n);
for(int i=2;i<=n;i++){
if(getfa(i)!=getfa(1)){
add1(i,1,0);
merge(1,i);
}
}
int q;
read(q);
while(q--){
read(x);
ans=0;
for(int i=1;i<=n;i++){
dfs(i,0,inf);
}
write_endl(ans/2);
} }
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
int t;
read(t);
while(t--){
solve();
puts("");
}
return 0;
}

3.[CQOI2016]不同的最小割

又一个板题,建出等价流树,根据性质可得,两点间的最小割为两点在等价流树上的路径上的边权最小值,所以统计有等价流树多少种不同边权即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=1010,M=600010,Lg=11,inf=1e9;
int n,m,head[N],hd[N],tot1=0,tot=1,id[N];
struct edge{
int v,w,nxt;
}e[M];
void add(int u,int v,int w){
e[++tot].v=v;
e[tot].nxt=head[u];
e[tot].w=w;
head[u]=tot;
}
set<int>s;
namespace GHT{
int dep[N],cur[N],tmp1[N],tmp2[N];
bool bfs(int S,int T){
for(int i=1;i<=n;i++){
dep[i]=0;
}
queue<int>q;
q.push(S);
dep[S]=1;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].v,w=e[i].w;
if(w&&!dep[v]){
dep[v]=dep[u]+1;
q.push(v);
if(v==T){
return 1;
}
}
}
}
return 0;
}
int dfs(int u,int flow,int T){
if(u==T){
return flow;
}
int s=0;
for(int i=cur[u];i;i=e[i].nxt){
cur[u]=i;
int v=e[i].v,w=e[i].w;
if(w&&dep[v]==dep[u]+1){
int res=dfs(v,min(flow,w),T);
e[i].w-=res;
e[i^1].w+=res;
flow-=res;
s+=res;
}
if(!flow){
break;
}
}
if(!s){
dep[u]=0;
}
return s;
}
void init(){
for(int i=0;i<=tot;i+=2){
e[i].w+=e[i^1].w;
e[i^1].w=0;
}
}
int dinic(int S,int T){
init();
int ans=0;
while(bfs(S,T)){
memcpy(cur,head,sizeof(head));
ans+=dfs(S,inf,T);
}
return ans;
}
void build(int l,int r){
if(l>=r){
return;
}
int x=id[l],y=id[l+1];
int flow=dinic(x,y);
s.insert(flow);
int cnt1=0,cnt2=0;
for(int i=l;i<=r;i++){
if(dep[id[i]]){
tmp1[++cnt1]=id[i];
}
else{
tmp2[++cnt2]=id[i];
}
}
for(int i=1;i<=cnt1;i++){
id[l+i-1]=tmp1[i];
}
for(int i=1;i<=cnt2;i++){
id[cnt1+i+l-1]=tmp2[i];
}
build(l,l+cnt1-1);
build(l+cnt1,r);
}
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n),read(m);
for(int i=1,u,v,w;i<=m;i++){
read(u),read(v),read(w);
add(u,v,w);
add(v,u,0);
add(v,u,w);
add(u,v,0);
}
for(int i=1;i<=n;i++){
id[i]=i;
}
GHT::build(1,n);
write_endl(s.size());
return 0;
}

4.cf343e

先想最暴力的做法,是不是枚举排列,然后跑最小割,求最小割的和的最大值。然后我们发现这样要把任意两个点之间的最小割都求出来,于是建出等价流树。

此时我们再看一下一个排列表示什么,表示的是给每个点标一个dfs序,然后按照dfs序在最小割树上搜一遍,因为等价流树的性质,所以最小割的和等于dfs序相邻的两点的路径上边权最小值的和。所以问题就转化为了求一个dfs序,使得最小割树上边权小的边尽量少走。

先讨论最小边的贡献的次数,只要经过最小边则必然造成一次贡献。因为要遍历整棵树,所以最小边至少经过一次,即最少造成一次贡献。

那么有可能造成更多的贡献吗?这是不可能的。

令最小边的两端点为 \(u,v\),若断掉最小边,则一棵树会变成两颗树,分别令 \(u,v\) 为根,那么这两棵树分别为树 \(u\) 和树 \(v\)。一个非常显然的事是,我们可以先遍历完树 \(u\),再遍历树 \(v\),这样最小边就只会造成 \(1\) 次贡献,同理每条边都会造成 \(1\) 次贡献,答案的最大值就为等价流树上边权之和,方案可以 \(n^2\) 扫一遍。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=300,M=1e4,inf=1e9;
int n,m,tot=1,tot1=1,head[N],hd[N],id[N],ans;
struct edge{
int u,v,w,nxt;
}e[M],G[M];
void add(int u,int v,int w){
e[++tot].v=v;
e[tot].w=w;
e[tot].nxt=head[u];
head[u]=tot;
}
void add1(int u,int v,int w){
G[++tot1].v=v;
G[tot1].u=u;
G[tot1].w=w;
G[tot1].nxt=hd[u];
ans+=w;
hd[u]=tot1;
}
namespace Gusfield{
int dep[N],cur[N],tmp1[N],tmp2[N];
bool bfs(int S,int T){
for(int i=1;i<=n;i++){
dep[i]=0;
}
queue<int>q;
q.push(S);
dep[S]=1;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].v,w=e[i].w;
if(w&&!dep[v]){
dep[v]=dep[u]+1;
q.push(v);
if(v==T){
return 1;
}
}
}
}
return 0;
}
int dfs(int u,int flow,int T){
if(u==T){
return flow;
}
int s=0;
for(int i=cur[u];i;i=e[i].nxt){
cur[u]=i;
int v=e[i].v,w=e[i].w;
if(w&&dep[v]==dep[u]+1){
int res=dfs(v,min(flow,w),T);
e[i].w-=res;
e[i^1].w+=res;
flow-=res;
s+=res;
}
if(!flow){
break;
}
}
if(!s){
dep[u]=0;
}
return s;
}
void init(){
for(int i=0;i<=tot;i+=2){
e[i].w+=e[i^1].w;
e[i^1].w=0;
}
}
int dinic(int S,int T){
init();
int ans=0;
while(bfs(S,T)){
memcpy(cur,head,sizeof(head));
ans+=dfs(S,inf,T);
}
return ans;
}
void build(int l,int r){
if(l>=r){
return;
}
int x=id[l],y=id[l+1];
int flow=dinic(x,y);
add1(x,y,flow);
add1(y,x,flow);
int cnt1=0,cnt2=0;
for(int i=l;i<=r;i++){
if(dep[id[i]]){
tmp1[++cnt1]=id[i];
}
else{
tmp2[++cnt2]=id[i];
}
}
for(int i=1;i<=cnt1;i++){
id[l+i-1]=tmp1[i];
}
for(int i=1;i<=cnt2;i++){
id[cnt1+i+l-1]=tmp2[i];
}
build(l,l+cnt1-1);
build(l+cnt1,r);
}
}
bool vis[M];
vector<int>s;
void get(int u,int fa){
s.pb(u);
for(int i=hd[u];i;i=G[i].nxt){
int v=G[i].v;
if(vis[i]||v==fa){
continue;
}
get(v,u);
}
}
void dfs(int u){
if(s.size()==1){
write_space(s[0]);
return;
}
int id=0,mn=inf;
for(auto x:s){
for(int i=hd[x];i;i=G[i].nxt){
if(vis[i]){
continue;
}
int w=G[i].w;
if(w<mn){
mn=w;
id=i;
}
}
}
cerr<<id/2<<endl;
vis[id]=vis[id^1]=1;
vector<int>().swap(s);
get(G[id].u,0);
dfs(G[id].u);
vector<int>().swap(s);
get(G[id].v,0);
dfs(G[id].v);
}
void solve(){
read(n),read(m);
for(int i=1,u,v,w;i<=m;i++){
read(u),read(v),read(w);
add(u,v,w);
add(v,u,0);
add(v,u,w);
add(u,v,0);
}
for(int i=1;i<=n;i++){
id[i]=i;
}
Gusfield::build(1,n);
write_endl(ans>>1);
for(int i=1;i<=n;i++){
s.pb(i);
}
dfs(1);
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
int t=1;
while(t--){
solve();
}
return 0;
}

Gusfield算法学习的更多相关文章

  1. DSP算法学习-过采样技术

    DSP算法学习-过采样技术 彭会锋 2015-04-27 23:23:47 参考论文: 1 http://wr.lib.tsinghua.edu.cn/sites/default/files/1207 ...

  2. 算法学习之C语言基础

    算法学习,先熟悉一下C语言哈!!! #include <conio.h> #include<stdio.h> int main(){ printf(+); getch(); ; ...

  3. Python之路,Day21 - 常用算法学习

    Python之路,Day21 - 常用算法学习   本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...

  4. C / C++算法学习笔记(8)-SHELL排序

    原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...

  5. 算法学习之BFS、DFS入门

    算法学习之BFS.DFS入门 0x1 问题描述 迷宫的最短路径 给定一个大小为N*M的迷宫.迷宫由通道和墙壁组成,每一步可以向相邻的上下左右四格的通道移动.请求出从起点到终点所需的最小步数.如果不能到 ...

  6. 二次剩余Cipolla算法学习笔记

    对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...

  7. Manacher算法学习笔记 | LeetCode#5

    Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...

  8. 第四百一十五节,python常用排序算法学习

    第四百一十五节,python常用排序算法学习 常用排序 名称 复杂度 说明 备注 冒泡排序Bubble Sort O(N*N) 将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮 ...

  9. PCA算法学习(Matlab实现)

    PCA(主成分分析)算法,主要用于数据降维,保留了数据集中对方差贡献最大的若干个特征来达到简化数据集的目的. 实现数据降维的步骤: 1.将原始数据中的每一个样本用向量表示,把所有样本组合起来构成一个矩 ...

  10. Javascript经典算法学习1:产生随机数组的辅助类

    辅助类 在几个经典排序算法学习部分,为方便统一测试不同算法,新建了一个辅助类,主要功能为:产生指定长度的随机数组,提供打印输出数组,交换两个元素等功能,代码如下: function ArraySort ...

随机推荐

  1. VS中多字节字符集和UNICODE字符集的使用说明

    两者的核心区别: 1.在制作多国语言软件时,使用Unicode(UTF-16,16bits,两个字节).无特殊要求时,还是使用多字节字符集比较好. 2.如果要兼容C编程,只能使用多字节字符集.这里的兼 ...

  2. 8-WebShell总结

    WebShell 1.webshell介绍 在计算机科学中,Shell 俗称壳(用来区别"核"),是指"为使用者提供操作界面"的软件(命令解释器).类似于win ...

  3. Sqoop导入MySQL表中数据到Hive出现错误: ERROR hive.HiveConfig: Make sure HIVE_CONF_DIR is set correctly.ERROR tool.ImportTool: Import failed:

    1.问题描述: (1)问题示例: [Hadoop@master TestDir]$ sqoop import --connect jdbc:mysql://master:3306/source?use ...

  4. AreEngine 求最小面积的外接矩形,非IEnvelope,表达不清楚了

    1,总是会得到一些奇奇怪怪的要求,求一个面对象的外接最小面积的矩形,和ArcToolBox中的Mininum Bounding Geometry功能下的RECTANGLE_BY_AREA想似.具体看下 ...

  5. Linux系统mysql免安装版配置指南

    1.下载(/usr/local目录) wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.32-linux-glibc2.12-x ...

  6. selenium 使用ddt,运行提示错误信息no such test method

    测试用例test_asg测试数据是通过ddt的方式添加,使用suite.addTest方法添加该用例提示错误信息no such test method in <class 'unitest_lo ...

  7. MySQL:查询语句 case when then 的用法

    转载网址: https://blog.csdn.net/h123hlll/article/details/122366213

  8. 抑制stable_secret读取关键信息

    如何抑制stable_secret读取关键的"net.ipv6.conf.all.stable_secret"消息? 您可以/dev/null使用以下命令抑制额外的不需要的消息或将 ...

  9. Android笔记--视图显示

    视图显示 视图的宽高设置 方式一:在.xml文件中设置视图的宽和高 通过调用android:layout_width设置视图的宽 通过调用android:layout_height设置视图的高 宽和高 ...

  10. 如何基于 Agora Android SDK 在应用中实现视频通话?

    在很多产品,实时视频通话已经不是新鲜的功能了,例如视频会议.社交应用.在线教育,甚至也可能出现在一些元宇宙的场景中. 本文将教你如何通过声网Agora 视频 SDK 在 Android 端实现一个视频 ...