zoukankan      html  css  js  c++  java
  • NOIp 图论基础

    从最害怕的专题到最喜欢的专题……嗯果然多刷题是最有用的w

    目录

    • 存图
      • 邻接矩阵
      • 链式前向星
      • vector
    • 最短路
      • SPFA(死了)
      • Floyed
      • 堆优化Dijkstra
      • 最短路计数
      • 严格次短路
      • 分层图最短路
    • 最小生成树
      • Kruskal
      • Prim
    • Tarjan
      • 强连通分量
      • 缩点
      • 割点
      • 离线LCA
    • 倍增LCA
    • 拓扑排序
    • 树的直径
      • dfs法
      • dp法
    • 差分约束
    • 网络流
      • 二分图匹配
      • 最大流
      • 费用流
    • 负环
    • 最小环
    • 欧拉回路

    一、存图

    1、邻接矩阵存图

    memset(mapp,128/3,sizeof mapp);
    	for(int i=1;i<=n;i++){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		mapp[u][v]=mapp[v][u]=min(mapp[u][v],w);
    	}
    

    2、链式前向星

    struct sth{
    	int to,nxt,dis;
    };
    int tot,head[MAXN];
    void add(int u,int v,int w){
    	a[++tot].to=v;a[tot].nxt=head[u];
    	a[tot].dis=w;head[u]=tot;
    }
    

    3、vector

    vector<int>P[MAXN];
    for(int i=1;i<=n;i++){
    	int u,v;
    	P[u].push_back(v);
    	P[v]=push_back(u);
    }
    

    以下内容均省去建图过程,一般是前向星存的。

    二、最短路

    1、SPFA (它曾活过啊)

    void SPFA(){
    	queue<int>q;	
    	memset(d,0x7f7f7f,sizeof d);
    	q.push(s);d[s]=0;vis[s]=1;
    	while(!q.empty()){
    		int noww=q.front();q.pop();
    		for(int j=head[noww];j;j=a[j].nxt){
    			int vv=a[j].to;
    			if(d[vv]>d[noww]+a[j].dis){
    				d[vv]=d[noww]+a[j].dis;
    				if(!vis[vv])q.push(vv),vis[vv]=1;
    			}
    		}vis[noww]=0;
    	}
    }
    

    2、Floyed

    void Floyed(){
    	for(int k=1;k<=n;k++)
    	  for(int i=1;i<=n;i++)
    	    for(int j=1;j<=n;j++){
    	      if(mapp[i][j]>mapp[i][k]+mapp[k][j])
    	        mapp[i][j]=mapp[i][k]+mapp[k][j];
    		}
    }
    

    3、堆优化Dijkstra

    struct node{
        int to,dis;
        bool operator <(const node &t) const{
            return dis>t.dis;
        }
    }a[MAXM<<1];
    priority_queue<node>q;
    void dij(){
    	for(int i=1;i<=m;i++)d[i]=2147483647;
    	d[s]=0;node qwq;qwq.to=s;qwq.dis=0;
        q.push(qwq);
        while(!q.empty()){
            node P=q.top();q.pop();
            int noww=P.to;
            if(visit[noww])continue;
            visit[noww]=1;
            for(int j=head[noww];j;j=nxt[j]){
                int vv=a[j].to;
                if(d[vv]>d[noww]+a[j].dis){
    			    d[vv]=d[noww]+a[j].dis;
                    node qwq;qwq.to=vv;qwq.dis=d[vv];
                    q.push(qwq);
                }
            }
        }
    }
    

    四、最短路计数

    void SPFA(){
        q.push(1);dis[1]=0;
    	t[1]=1;vis[1]=1;
        while(!q.empty()){
            int noww=q.front();q.pop();
            if(noww==n)continue;//重要 
            for(int i=1;i<=n;i++){
                if(dis[noww]+a[noww][i]==dis[i])
                t[i]+=t[noww];
                if(dis[noww]+a[noww][i]<dis[i]){
                    dis[i]=dis[noww]+a[noww][i];
                    t[i]=t[noww];
                }
    		    if(t[i]&&!vis[i])vis[i]=1,q.push(i);
            }
    		t[noww]=0,vis[noww]=0;//重要 
        }
    }
    

    五、严格次短路

    priority_queue<P,vector<P>,greater<P> >q;
    void dij(){
        for(int i=1;i<=n;i++)d1[i]=d2[i]=inf;
        d1[1]=0;
        q.push(P(1,0));
        while(!q.empty()){
            int noww=q.top().first;
            int d=q.top().second;q.pop();
            for(int j=head[noww];j;j=a[j].nxt){
                int vv=a[j].to;int disv=a[j].dis+d;
                if(disv<d1[vv]){
                    swap(d1[vv],disv);//重要 
                    q.push(P(vv,d1[vv]));
                }
                if(disv>d1[vv]&&disv<d2[vv]){
                    d2[vv]=disv;
                    q.push(P(vv,d2[vv]));
                }
            }
        }
    }
    

    六、分层图最短路

    了解了算法就一眼能瞪出正解的题型...

    例题

    建一个k+1层的图,层内连边,层之间连0边即可。(其实是dp思想)

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=200005;
    const int MAXM=6000005;
    int n,m,k,tot,head[MAXN],s,t;
    int d[MAXN];
    struct sth{
    	int to,nxt,dis;
    }a[MAXM];
    struct node{
    	int qwq,diss;
    	bool operator <(const node& t)const{
    	    return diss>t.diss;
    	}
    }; 
    priority_queue<node>q;
    void add(int u,int v,int w){
    	a[++tot].dis=w;a[tot].to=v;
    	a[tot].nxt=head[u];head[u]=tot;
    }
    void dij(){
    	memset(d,128/3,sizeof d);d[s]=0;
    	node ss;ss.diss=0;ss.qwq=s;q.push(ss);
    	while(!q.empty()){
    		node noww=q.top();q.pop();
    		int nowq=noww.qwq;
    		for(int j=head[nowq];j;j=a[j].nxt){
    			int vv=a[j].to;
    			if(d[vv]>d[nowq]+a[j].dis){
    				d[vv]=d[nowq]+a[j].dis;
    				node orz;orz.qwq=vv;orz.diss=d[vv];
    				q.push(orz);
    			}
    		}
    	}
    	
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&k);
    	scanf("%d%d",&s,&t);s++;t++;
    	for(int i=1;i<=m;i++){
    		int u,v,w;scanf("%d%d%d",&u,&v,&w);
    		u++;v++;
    		for(int j=0;j<=k;j++){
    			add(u+j*n,v+j*n,w);add(v+j*n,u+j*n,w);
    			if(j!=k){
    				add(u+j*n,v+(j+1)*n,0);
    				add(v+j*n,u+(j+1)*n,0);
    			}
    		}
    	}
    	for(int j=0;j<k;j++){
    		add(t+n*j,t+n*(j+1),0);
    		add(t+n*(j+1),t+n*j,0);
    	}
    	dij();
    	printf("%d
    ",d[t]);
    	return 0;
    }
    

    七、最小生成树

    1、适合稀疏图的Kruskal

    void qsort(int l,int r){
        int i=l,j=r;node mid=a[(i+j)/2];
        while(i<=j){
            while(cmp(a[i],mid))i++;
            while(cmp(mid,a[j]))j--;
            if(i<=j){
                t=a[i];a[i]=a[j];a[j]=t;
                i++;j--;
            }
        }
        if(i<r)qsort(i,r);
        if(l<j)qsort(l,j);
    }
    int findx(int x){return (x==fa[x])?fa[x]:fa[x]=findx(fa[x]);}
    void solve(){
        qsort(1,m);
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            if(findx(a[i].x)!=findx(a[i].y)){
                ans+=a[i].w;
                fa[findx(a[i].x)]=a[i].y;
                p++;
                if(p==n)return ;
            }
        }
    }
    

    2、适合稠密图的Prim

    (都8012年了我才会Prim)

    void Prim(){
    	for(int i=1;i<=n;i++){
    		mincost[i]=mapp[1][i];
    	}
    	use[1]=1;//重要 
    	for(int i=1;i<n;i++){
    		int minn=99999999;
    		int j;
    		for(int k=1;k<=n;k++){
    			if(!use[k]&&mincost[k]<minn){
    				j=k;
    				minn=mincost[k];
    			}
    		}
    		use[j]=1;
    		ans+=minn;
    		for(int k=2;k<=n;k++){
    			if(!use[k]&&mincost[k]>mapp[j][k]){
    				mincost[k]=mapp[j][k];
    			}
    		}
    	}
    }
    
    

    八、Tarjan

    1、强联通分量

    int dfs(int x){
    	dfn[x]=low[x]=++cntt;
    	vis[x]=1;s.push(x);
    	for(int j=head[x];j;j=a[j].nxt){
    		int vv=a[j].to;
    		if(!dfn[vv]){
    			int lowv=dfs(vv);
    			low[x]=min(low[x],lowv);
    		}
    		else{
    			if(vis[vv]){
    				low[x]=min(low[x],low[vv]); 
    			}
    		}
    	}
    	if(dfn[x]==low[x]){
    		cntcol++;colour[x]=cntcol;cnt[cntcol]++;
    		vis[x]=0;
    		sta[cntcol][1]=x;
    		while(s.top()!=x){
    			colour[s.top()]=cntcol;cnt[cntcol]++;
    			vis[s.top()]=0;sta[cntcol][cnt[cntcol]]=s.top();
    			s.pop();
    		}s.pop();
    		maxcnt=max(maxcnt,cnt[cntcol]);
    	}
    	return low[x];
    }
    void tarjan(){
    	for(int i=1;i<=n;i++){
    		if(!dfn[i])dfs(i);
    	}
    }
    

    2、缩点

    int tarjan(int u){
        dep++;vis[u]=1;
        s.push(u);
        int lowu=dep;dfn[u]=low[u]=dep;
        for(int j=head[u];j;j=a[j].nxt){
            int vv=a[j].to;
            if(!dfn[vv]){
                int lowv=tarjan(vv);
                lowu=min(lowu,lowv);
            }else{
                if(vis[vv])
                lowu=min(lowu,low[vv]);
            }
        }
        low[u]=lowu;
        if(low[u]==dfn[u]){
            cnt++;
            colour[u]=cnt;vis[u]=0;
            newq[cnt]+=q[u];
            while(s.top()!=u){
                colour[s.top()]=cnt;
                newq[cnt]+=q[s.top()];
                vis[s.top()]=0;
                s.pop();
            }s.pop();
        }
        return lowu;
    }
    void work(){
        for(int i=1;i<=n;i++){
            if(!dfn[i])tarjan(i);
        }
        for(int i=1;i<=m;i++)
            if(colour[x[i]]!=colour[y[i]])add(colour[x[i]],colour[y[i]]);
    }
    

    3、割点

    void tarjan(int u,int fa){
    	int ch=0;dep++;
    	dfn[u]=low[u]=dep;
    	for(int j=head[u];j;j=a[j].nxt){
    		int vv=a[j].to;
    		if(!dfn[vv]){
    			ch++;
    			tarjan(vv,u);
    			low[u]=min(low[u],low[vv]);
    			if(low[vv]>=dfn[u])iscut[u]=1;
    		}else{
    			if(vv!=fa&&dfn[vv]<dfn[u])
    			low[u]=min(low[u],low[vv]);
    		}
    	}
    	if(fa==-1&&ch==1)iscut[u]=0;
    	if(fa==-1&&ch>=2)iscut[u]=1;
    }
    void work(){
    	for(int i=1;i<=n;i++){
    		if(!dfn[i])tarjan(i,-1);
    	}
    }
    

    4、桥

    void tarjan(int u,int fa){
    	int ch=0;dep++;
    	dfn[u]=low[u]=dep;
    	for(int j=head[u];j;j=a[j].nxt){
    		int vv=a[j].to;
    		if(!dfn[vv]){
    			ch++;
    			tarjan(vv,u);
    			low[u]=min(low[u],low[vv]);
    			if(dfn[u]<low[vv])printf("%d %d
    ",u,vv); 
    		}else{
    			if(vv!=fa&&dfn[vv]<dfn[u])
    			low[u]=min(low[u],low[vv]);
    		}
    	}
    }
    void work(){
    	for(int i=1;i<=n;i++){
    		if(!dfn[i])tarjan(i,-1);
    	}
    }
    

    5、离线求LCA

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=505;
    int n,m,root;
    struct sth{
    	int nxt,to,lca;
    }a[MAXN],b[MAXN];
    int tot,toot,head[MAXN],head2[MAXN];
    void add(int u,int v){
    	a[++tot].to=v;a[tot].nxt=head[u];
    	head[u]=tot;
    }
    void add2(int u,int v){
    	b[++toot].to=v;b[toot].nxt=head2[u];
    	head2[u]=toot;
    }
    bool vis[MAXN];
    int fa[MAXN];
    int find(int x){return x==fa[x]?fa[x]:fa[x]=find(fa[x]);}
    void dfs(int x){
    	fa[x]=x;
    	vis[x]=1;
    	for(int j=head[x];j;j=a[j].nxt){
    		int vv=a[j].to;
    		if(!vis[vv]){
    			dfs(vv);
    			fa[vv]=x;
    		}
    	}
    	for(int j=head2[x];j;j=b[j].nxt){
    		int vv=b[j].to;
    		if(vis[vv]){
    			b[j].lca=find(vv);
    			if(j&1)
    			   b[j+1].lca=b[j].lca;
    			else b[j-1].lca=b[j].lca;
    		}
    	}
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&root);
    	for(int i=1;i<n;i++){
    		int u,v;
    		scanf("%d%d",&u,&v);
    		add(u,v);add(v,u);
    	}
    	for(int i=1;i<=m;i++){
    		int u,v;
    		scanf("%d%d",&u,&v);
    		add2(u,v);add2(v,u);
    	}
    	dfs(root);
    	for(int i=1;i<=toot;i+=2)printf("%d
    ",b[i].lca);
    	return 0;
    }
    

    九、倍增求LCA

    void dfs(int u,int f,int d){
    	fa[u][0]=f;deep[u]=d;
    	for(int i=head[u];i;i=a[i].nxt){
    		int vv=a[i].to;
    		if(vv!=f)dfs(vv,u,d+1);
    	}
    }
    int lca(int u,int v){
    	if(deep[u]>deep[v])swap(u,v);
    	for(int k=0;k<19;k++){
    		if(((deep[v]-deep[u])>>k)&1)v=fa[v][k];
    	}if(u==v)return u;
    	for(int k=18;k>=0;k--){
    		if(fa[v][k]!=fa[u][k]){
    			u=fa[u][k];v=fa[v][k];
    		}
    	}return fa[u][0];
    }
    void work(){
    	dfs(root,-1,0);
    	for(int k=0;k+1<19;k++){
    		for(int j=1;j<=n;j++)
    		if(fa[j][k]<0)fa[j][k+1]=-1;
    		else fa[j][k+1]=fa[fa[j][k]][k];	
    	}
    } 
    

    十、拓扑排序

    void tuopu(){//不断找入度为0的点
    	for(int i=1;i<=n;i++)if(!rudu[i])q.push(i);
    	while(!q.empty()){
    		int noww=q.front();q.pop();
    		tp[++cnt]=noww;
    		for(int j=head[noww];j;j=a[j].nxt){
    			int vv=a[j].to;rudu[vv]--;
    			if(!rudu[vv])q.push(vv);
    		}
    	}if(cnt!=n){
    		printf("No Solution!
    ");return;
    	}
    	for(int i=1;i<=cnt;i++)printf("%d ",tp[i]);
    	printf("
    ");
    }
    

    十一、树的直径

    “你知道吗,树的直径有两种求法。”
    (好像还可以bfs求,然而我没写过)

    1、两遍dfs求法

    void dfs(int noww){
    	if(dis[noww]>maxn){
    		maxn=dis[noww];
    		t=noww;
    	}
        vis[noww]=1;
        for(int j=head[noww];j;j=a[j].nxt){
            int vv=a[j].to;
            if(!vis[vv]){
                dis[vv]=dis[noww]+a[j].to;
                dfs(vv);
            }
        }
    }
    void work(){
    	maxn=-99999999;
    	memset(vis,0,sizeof vis);
    	memset(dis,128/3,sizeof dis);
    	dis[1]=0;
    	dfs(1);
    	s=t;
    	maxn=-99999999;
    	memset(vis,0,sizeof vis);
    	memset(dis,128/3,sizeof dis);
    	dis[s]=0;
    	dfs(s);
    }
    
    

    2、dp求法

    void dfs(int noww,int from) {
        dp[noww][0]=0;dp[noww][1]=0;
        for (int j=head[noww];j;j=a[j].nxt){
            int vv=a[j].to;
            if(vv!=from){
                dfs(vv,i);
                if (dp[vv][0]+a[j].dis>dp[i][0]){
                    dp[i][1]=dp[i][0];
                    dp[i][0]=dp[vv][0]+a[j].dis;
                }
                else if(dp[to[j]][0]+a[j].dis>dp[i][1])
                        dp[i][1]=dp[vv][0]+a[j].dis;
            }
        }
        ans=max(ans,dp[i][0]+dp[i][1]);
    }//dfs(1,-1);
    

    十二、差分约束

    差分约束并没有固定的模板,但有固定的套路——

    将条件中的差值不等式转换成最短路松弛时的不等式即可。

    以洛谷P3275糖果一题为例,将五种要求转化成连边,跑SPFA。

    不能成立的条件是出现环。

    这里给出建图和最短路部分

    bool SPFA(){
        vis[0]=1,q.push(0);
        while(!q.empty()){
            int u=q.front();q.pop();vis[u]=0;
            if(tot[u]==n-1){cout<<-1;return 0;}
            tot[u]++;
            for(int i=head[u];i;i=a[i].nxt)
                if(d[a[i].to]<d[u]+a[i].dis){
                    d[a[i].to]=d[u]+a[i].dis;
                    if(!vis[a[i].to])vis[a[i].to]=1,q.push(a[i].to);
                }
        }return 1;
    }
    void init(){
    	for(ll i=1;i<=k;i++){
            ll opt,u,v;
            cin>>opt>>u>>v;
            if(opt==1){
                add(u,v,0);add(v,u,0);
            }
            if(opt==2){
                add(u,v,1);
                if(u==v){
                    cout<<"-1";return 0;
                }
            }
            if(opt==3){
                add(v,u,0);
            }
            if(opt==4){
                add(v,u,1);if(u==v){
                    cout<<"-1";return 0;
                }
            }
            if(opt==5){
                add(u,v,0);
            }
        }
        for(ll i=n;i>=1;i--)add(0,i,1);
    }
    

    十三、网络流

    1、二分图匹配

    当然可以跑网络流,然而二分图匹配更好写。(算法名字我分不清....)

    bool dfs(int x){
    	for(int j=1;j<=m;j++){
    		if(!mapp[x][j])continue;
    		if(use[j])continue;
    		use[j]=1;
    		if(!match[j]||dfs(match[j])){
    			match[j]=x;
    			return 1;
    		}
    	}
    	return 0;
    }
    void work(){
    	for(int i=1;i<=n;i++){
    	    memset(use,0,sizeof use);
    		if(dfs(i))ans++;
    	}
    }
    

    2、最大流

    int bfs(){
        memset(deep,0,sizeof(deep));
        queue<int>q;
        deep[s]=1;
        q.push(s);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u];i!=-1;i=e[i].nxt){
                if(e[i].dis&&!deep[e[i].to]){
                    deep[e[i].to]=deep[u]+1;
                    q.push(e[i].to);
                }
            }
        }
        if(deep[t])return 1;
        return 0;
    }
    int dfs(int u,int d) {
        if(u==t)return d;
        for(int i=head[u];i!=-1;i=e[i].nxt){
            if((deep[e[i].to]==deep[u]+1)&&(e[i].dis)){
                int di=dfs(e[i].to,min(d,e[i].dis)); 
                if(di){
                    e[i].dis-=di;
                    e[i^1].dis+=di;
                    return di;
                }
            }
        }
        return 0;
    }
    int dinic(){
        int ret=0;
        while(bfs())
            while(int di=dfs(s,INF)) 
                ret+=di;
        return ret;
    }
    
    

    还有最大流最小割定理。我不会证也懒得copy了...

    3、费用流

    把最大流的bfs改成SPFA就好啦

    int spfa(){
        memset(d,0x7f,sizeof(d));
        d[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;i=a[i].nxt){
                int vv=a[i].to;
                if(a[i].dis&&d[u]+a[i].cost<d[vv]){
                    d[vv]=d[u]+a[i].cost;
                    if(!vis[vv])vis[vv]=1,q.push(vv);
                }
            }
        }
        return d[t];
    }
    int dfs(const int u,const int f){
        if(f==0||u==t)return f;
        int ret=0;vis[u]=1;
        for(int i=cur[u];i;i=a[i].nxt){
            cur[u]=i;
            int v=a[i].to;
            if(d[v]!=d[u]+a[i].cost||!a[i].dis)continue;
            if(!vis[v]){
                int ans=dfs(v,min(f-ret,a[i].dis));
                ret+=ans;
    			a[i].dis-=ans,a[i^1].dis+=ans;
                mincost+=a[i].cost*ans;
            }
        }
        vis[u]=0;
        return ret;
    }
    void dinic(){
        while(spfa()!=0x7f7f7f7f){
            for(int i=1;i<=n;i++)cur[i]=head[i];
            while(int x=dfs(s,0x7f7f7f7f)){
                maxflow+=x;
                if(mincost>=0x7f7f7f2b)return;
            }
        }
    }
    

    十四、负环

    如果有一个点入队次数大于(n),那么一定有负环

    bool SPFA(int s){
    	queue<int>q;
    	memset(vis,0,sizeof vis);
    	memset(d,128/3,sizeof d);
    	d[s]=0;vis[s]=1;cnt[s]=1;q.push(s);
    	while(!q.empty()){
    		int noww=q.front();q.pop();vis[noww]=0;
    		for(int j=head[noww];j;j=a[j].nxt){
    		int vv=a[j].to;
    		if(d[vv]>d[noww]+a[j].dis){
    			d[vv]=d[noww]+a[j].dis;
    			cnt[vv]=cnt[noww]+1;
    			if(cnt[vv]>n)return 0;
    			if(!vis[vv])vis[vv]=1,q.push(vv);	
    		}
    		}
    	}return 1;
    }
    
    

    十五、最小环

    只见过一道求最小环的题,感觉很有意思,值得一做。(虽然这道题的精髓在于建图)

    for(int k=1;k<=a;k++){
    	for(int i=1;i<=k-1;i++)
    		for(int j=i+1;j<=k-1;j++){
    		  	int tmp=qwq[i][j]+dis[i][k]+dis[k][j];
    		  	if(tmp<ans)ans=tmp;	
    		    }		  
    	for(int i=1;i<=a;i++)
    		for(int j=1;j<=a;j++){
    		    if(qwq[i][j]>qwq[i][k]+qwq[k][j])
    		    qwq[i][j]=qwq[i][k]+qwq[k][j];
    	    }
    }
    

    正确性证明:在枚举环上的(ij)时,因为这两个点没有被(k)松弛过,所以必定不会经过(k)

    十六、欧拉回路

    void dfs(int x){
        for (int i=1;i<=n;i++)
        if (mapp[x][i]){
            mapp[x][i]--;
    		mapp[i][x]--;
            dfs(i);
        }
    	S.push(x);
    }
    void work(){
    	for(int i=1;i<=m;i++){
            int u,v;scanf("%d%d",&u,&v);
            mapp[u][v]++;
    		mapp[v][u]++;
            b[u]++;b[v]++;
            n=max(n,max(u,v));
        }
        s=1;int cnt=0;
        for(int i=n;i>=1;i--)
    	if(b[i]&1)s=i,cnt++;
        if(cnt&&cnt!=2){
            printf("No Solution!
    ");
            exit(0);
    	}
    	dfs(s);
    } 
    
    
    
  • 相关阅读:
    封装成帧、帧定界、帧同步、透明传输(字符计数法、字符串的首尾填充法、零比特填充的首尾标志法、违规编码法)
    计算机网络之数据链路层的基本概念和功能概述
    物理层设备(中继器、集线器)
    计算机网络之传输介质(双绞线、同轴电缆、光纤、无线电缆、微波、激光、红外线)
    计算机网络之编码与调制
    0953. Verifying an Alien Dictionary (E)
    1704. Determine if String Halves Are Alike (E)
    1551. Minimum Operations to Make Array Equal (M)
    0775. Global and Local Inversions (M)
    0622. Design Circular Queue (M)
  • 原文地址:https://www.cnblogs.com/erutsiom/p/9923640.html
Copyright © 2011-2022 走看看