板子哲学康复练习
开学后第一次用 Windows 打代码,有种唐氏儿的美。
Tarjan
tarjan 求强连通
不知道有没有过编,但大概没错。
Miku's Code
#include<bits;/stdc++.h> #define rg register int #define il inline il int Min(int x,int y){ return x<y?x:y; } il int Max(int x,int y){ return x<y?y:x; } il int Abs(int x,int y){ return x<0?-x:x; } il int read(){ char c=getchar();int f=1,x=0; while(c<48){ if(c=='-')f=-1;c=getchar(); } while(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; } int n,m,a[maxn]; int dfn[maxn], int head[maxn<<1],t; struct Edge{ int v,w;int next; };Edge e[maxn<<1]; il void add_edge(int u,int v,int w){ e[++t].v=v;e[t].w=w;e[t].next=head[u];head[u]=t; } void tarjan(int now){ dfn[now]=low[now]=++cnt; for(rg i=head[now];i;i=e[i].next){ int to=e[i].v; if(!dfn[to]){ tarjan(to); low[now]=Min(low[now],low[to]); } else if(vis[to]) low[now]=Min(low[now],dfn[to]); } if(dfn[now]==low[now]){ int cur;++id; do{ cur=stk[top--];vis[cur]=false; scc[cur]=id;++siz[id]; }while(cur!=now); } } il void input(){ n=read(),m=read();int u,v,w; for(rg i=1;i<=n;++i) a[i]=read(); for(rg i=1;i<=m;++i) u=read(),v=read(),w=read(),add_edge(u,v,w); } int main(){ input(); for(rg i=1;i<=n;++i) if(!dfn[i]) tarjan(i); return 0; }
tarjan 求环
写了一个最小环版本的,过了。
恼了,有强联通分量好像 tarjan 没法求环,那打好像没啥意义啊。
Miku's Code
#include<bits/stdc++.h> #define rg register int #define il inline #define cerr std::cerr #define endl '\n' il int Max(int x,int y){ return x<y?y:x; } il int Min(int x,int y){ return x<y?x:y; } il int Abs(int x){ return x<0?-x:x; } il int read(){ char c=getchar();int x=0,f=1; while(c<48){ if(c=='-')f=-1;c=getchar(); } while(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; }const int maxn=2e5+5,inf=0x3f3f3f3f; int n,m,minn,id,a[maxn],dfn[maxn],low[maxn],tot,stk[maxn],top; bool invis[maxn]; int head[maxn<<1],t; struct Edge{ int v;int next; };Edge e[maxn<<1]; il void add_edge(int u,int v){ e[++t].v=v;e[t].next=head[u];head[u]=t; } void tarjan(int now){ dfn[now]=low[now]=++tot; stk[++top]=now;invis[now]=true; for(rg i=head[now];i;i=e[i].next){ int to=e[i].v; if(!dfn[to]){ tarjan(to); low[now]=Min(low[now],low[to]); } else if(invis[to]) low[now]=Min(low[now],dfn[to]); } if(dfn[now]==low[now]){ int cur=stk[top],count_=0; while(cur!=now){ ++count_;invis[cur]=false; --top;cur=stk[top]; } ++count_; invis[cur]=false;--top; if(count_>1) minn=Min(minn,count_); } } il void input(){ n=read();int v; for(rg i=1;i<=n;++i) v=read(),add_edge(i,v); } int main(){ // freopen("tarjan.in","r",stdin); input();minn=inf; for(rg i=1;i<=n;++i) if(!dfn[i]) tarjan(i); printf("%d\n",minn); return 0; }
tarjan 求点双
我去我不会啊,抄了一遍板子。
Miku's Code
// 点双联通:删掉一个点后子图仍为强联通分量 #include<bits/stdc++.h> #define il inline #define rg register int #define cerr std::cerr #define endl '\n' il int Min(int x,int y){ return x<y?x:y; } il int Max(int x,int y){ return x<y?y:x; } il int Abs(int x){ return x<0?-x:x; } il int read(){ char c=getchar();int x=0,f=1; while(c<48){ if(c=='-')f=-1;c=getchar(); } while(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; }const int maxn=1e5+5,maxm=3e5+5; int n,m,dfn[maxn],low[maxn],tot,stk[maxn],top,rt,cut[maxn],id[maxn],num; bool invis[maxn]; int head[maxm<<1],t; struct Edge{ int u,v;int next; };Edge e[maxm]; il void add_edge(int u,int v){ e[++t].v=v;e[t].next=head[u];head[u]=t; } std::vector<int> g[maxn]; std::vector<int> dcc[maxn];int rc; void tarjan(int now){ dfn[now]=low[now]=++tot; stk[++top]=now;invis[now]=true; if(now==rt && !head[now]) return dcc[++rc].push_back(now),void(); int child=0; for(rg i=head[now];i;i=e[i].next){ int to=e[i].v; if(!dfn[to]){ tarjan(to); low[now]=Min(low[now],low[to]); if(low[now]>=dfn[now]){ ++child; if(now!=rt || child>1) cut[now]=true; ++rc; printf("vDCC:"); int cur=stk[top]; while(cur!=to){ dcc[rc].push_back(cur);printf("%d ",cur); --top;cur=stk[top]; } dcc[rc].push_back(cur);printf("%d ",cur); --top; dcc[rc].push_back(now),printf("%d",now); } } else if(invis[to]) low[now]=Min(low[now],dfn[to]); } } int main(){ input(); for(rt=1;rt<=n;++rt) if(!dfn[rt]) tarjan(rt); for(rg i=1;i<=n;++i) if(cut[i]) id[i]=++num; memset(head,0,sizeof(head));t=0; for(rg i=1;i<=rc;++i){ for(rg j=0;j<dcc[i].size();++j){ int x=dcc[i][j]; if(cut[x]) g[i].push_back(id[x]),g[id[x]].push_back(i); } } return 0; }
tarjan 求边双
本来想写一个还需要多少边可连边双,但是懒得写了。
抄了遍板子,恼了,为啥我啥也不会。
Miku's Code
#include<bits/stdc++.h> const int maxn=5e3+5,maxm=3e5+5; int n,m,rt,dfn[maxn],low[maxn],tot,dcc[maxn],cnt; bool cut[maxn],invis[maxn]; int stk[maxn],top; int head[maxm],t; struct Edge{ int v;int next; };Edge e[maxm]; il void add_edge(int u,int v){ e[++t].v=v;e[t].next=head[u];head[u]=t; } void tarjan(int now,int fa){ dfn[now]=low[now]=++tot; stk[++top]=now;invis[now]=true; for(rg i=head[now];i;i=e[i].next){ int to=e[i].v; if(to==fa) continue; if(!dfn[to]){ tarjan(to,now); low[now]=Min(low[now],low[to]); } else if(vis[to]) low[now]=Min(low[now],low[to]); } if(dfn[now]==low[now]){ ++cnt;int cur=stk[top]; while(cur!=now){ dcc[cur]=cnt; --top;cur=stk[top];invis[cur]=false; } invis[cur]=false;dcc[cur]=cnt;--top; } } int main(){ tarjan(1,0); }
ST 表
应该没错,好像如果要检查的话还要🐎倍增,但是懒。
Miku's Code
#include<bits/stdc++.h> #define il inline #define rg register int #define cerr std::cerr #define endl '\n' il int Max(int x,int y){ return x<y?y:x; } il int Min(int x,int y){ return x<y?x:y; } il int Abs(int x){ return x<0?-x:x; } il int read(){ char c=getchar();int x=0,f=1; while(c<48){ if(c=='-')f=-1;c=getchar(); } while(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; }const int maxn=5e5+5; int n,q,max[maxn][20],min[maxn][20]; int query_max(int l,int r){ int k=log2(r-l+1); return Max(max[l][k],max[r-(1<<k)+1][k]); } int query_min(int l,int r){ int k=log2(r-l+1); return Min(min[l][k],min[r-(1<<k)+1][k]); } il void input(){ n=read(),q=read(); for(rg i=1;i<=n;++i) max[i][0]=min[i][0]=read(); for(rg j=1;j<19;++j) for(rg i=1;i+(1<<j)-1<=n;++i){ max[i][j]=Max(max[i][j-1],max[i+(1<<(j-1))][j-1]); min[i][j]=Min(min[i][j-1],min[i+(1<<(j-1))][j-1]); } } int main(){ input(); return 0; }
最短路&最小生成树
Floyed
呃呃,复习一个 Floyed 求最小环吧,过了。
Miku's Code
#include<bits/stdc++.h> #define il inline #define rg register int #define cerr std::cerr #define endl '\n' #define int long long il int Max(int x,int y){ return x<y?y:x; } il int Min(int x,int y){ return x<y?x:y; } il int Abs(int x){ return x<0?-x:x; } il int read(){ char c=getchar();int x=0,f=1; while(c<48){ if(c=='-')f=-1;c=getchar(); } while(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; }const int maxn=105,maxm=5e3+5,inf=0x3f3f3f3f3f3f; int n,m; int dis[maxn][maxn],dist[maxn][maxn],ans; struct Edge{ int v,w; };Edge e[maxm]; il void floyed(){ ans=inf; for(rg k=1;k<=n;++k){ for(rg i=1;i<k;++i) for(rg j=i+1;j<k;++j) ans=Min(ans,dist[i][j]+dis[i][k]+dis[k][j]); for(rg i=1;i<=n;++i) for(rg j=1;j<=n;++j) dist[i][j]=dist[j][i]=Min(dist[i][j],dist[i][k]+dist[k][j]); } } il void input(){ n=read(),m=read();int u,v,w; for(rg i=1;i<=n;++i) for(rg j=1;j<i;++j) dis[i][j]=dis[j][i]=dist[i][j]=dist[j][i]=inf; for(rg i=1;i<=m;++i) u=read(),v=read(),w=read(),dist[u][v]=dist[v][u]=dis[u][v]=dis[v][u]=Min(dis[u][v],w); } signed main(){ input(); floyed(); (ans==inf)?puts("No solution."):printf("%d\n",ans); return 0; }
堆优化 dijkstra
哈哈,这个要是错了真是贻笑大方了。
Miku's Code
#include<bits/stdc++.h> using namespace std; #define il inline #define rg register int typedef std::pair<int,int> PII; il int Max(int x,int y){ return x<y?y:x; } il int Min(int x,int y){ return x<y?x:y; } il int Abs(int x){ return x<0?-x:x; } il int read(){ char c=getchar();int x=0,f=1; if(c<48){ if(c=='-')f=-1;c=getchar(); } if(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; }const int maxn=5e5+5,inf=0x3f3f3f3f; int n,m,dis[maxn],ans; 这里是链式前向星 bool vis[maxn]; il void clear(){ for(rg i=0;i<=n;++i) dis[i]=inf,vis[i]=false; } void dijkstra(int now){ clear(); dis[now]=0; std::priority_queue<PII,vector<PII>,greater<PII>> heap; while(!heap.empty()) heap.pop(); heap.push(make_pair(0,now)); while(!heap.empty()){ PII t=heap.top();heap.pop(); int temp=t.second,distance=t.first; if(vis[temp]==true) continue; vis[temp]=true; for(rg i=head[temp];i;i=e[i].next){ int j=e[i].v; if(distance+e[i].w<dis[j]) dis[j]=distance+e[i].w,heap.push(make_pair(dis[j],j)); } } } int main(){ return 0; }
kruskal 最小生成树
跟板子对过了,应该没错。
Miku's Code
#include<bits/stdc++.h> #define il inline #define rg register int il int Max(int x,int y){ return x<y?y:x; } il int Min(int x,int y){ return x<y?x:y; } il int Abs(int x){ return x<0?-x:x; } il int read(){ char c=getchar();int x=0,f=1; while(c<48){ if(c=='-')f=-1;c=getchar(); } while(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; }const int maxn=1e5+5,maxm=3e5+5; int n,m,fa[maxn]; int getfa(int x){ return fa[x]==x?x:fa[x]=getfa(fa[x]); } int head[maxn<<1],t; struct Edge{ int u,v,w;int next; Edge()=default; Edge(int uu,int vv,int ww):u(uu),v(vv),w(ww) {} bool operator<(const Edge &e){ return w<e.w; } };Edge g[maxm],e[maxn<<1]; il void add_edge(int u,int v,int w){ e[++t].v=v;e[t].next=head[u];head[u]=t; } il void kruskal(){ std::sort(g+1,g+1+m); for(rg i=1;i<=m;++i){ if(getfa(g[i].u)!=getfa(g[i].v)){ add_edge(g[i].u,g[i].v,g[i].w);add_edge(g[i].v,g[i].u,g[i].w); fa[g[i].u]=getfa(e[i].v); } } } il void input(){ n=read(),m=read(); for(rg i=1;i<=n;++i) fa[i]=i; for(rg i=1;i<=m;++i) g[i]=Edge(read(),read(),read()); } int main(){ input(); kruskal(); return 0; }
Borůvka (Sollin)
时间复杂度 。
Miku's Code
#include<bits/stdc++.h> #define il inline #define rg register int il int Max(int x,int y){ return x<y?y:x; } il int Min(int x,int y){ return x<y?x:y; } il int Abs(int x){ return x<0?-x:x; } il int read(){ char c=getchar();int x=0,f=1; while(c<48){ if(c=='-')f=-1;c=getchar(); } while(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; }const int maxn=5e3+5,maxm=2e5+5,inf=0x3f3f3f3f; int n,m,fa[maxn],ans,res; int getfa(int x){ return x==fa[x]?x:fa[x]=getfa(fa[x]); } struct Edge{ int u,v,w,id; Edge()=default; Edge(int uu,int vv,int ww,int temp):u(uu),v(vv),w(ww),id(temp) {} };Edge e[maxm]; int minn[maxm],eid[maxm]; bool vis[maxm]; il void Boruvka(){ for(rg i=1;i<=n;++i) fa[i]=i; while(1){ int cnt=0; for(rg i=1;i<=n;++i) minn[i]=inf; for(rg i=1;i<=m;++i){ int fx=getfa(e[i].u),fy=getfa(e[i].v),w=e[i].w; if(fx==fy) continue; ++cnt; if(w<minn[fx] || (w==minn[fx] && e[i].id<eid[fx])) minn[fx]=w,eid[fx]=e[i].id; if(w<minn[fy] || (w==minn[fy] && e[i].id<eid[fy])) minn[fy]=w,eid[fy]=e[i].id; } if(cnt==0) break; for(rg i=1;i<=n;++i){ if(minn[i]!=inf && !vis[eid[i]]){ fa[getfa(e[eid[i]].u)]=getfa(e[eid[i]].v); ans+=e[eid[i]].w;++res; vis[eid[i]]=true; } } } } il void input(){ n=read(),m=read(); for(rg i=1;i<=m;++i) e[i]=Edge(read(),read(),read(),i); } int main(){ input(); Boruvka(); return 0; }
KMP
如果要考字符串的话,感觉大概率考 KMP 了啊。
Miku's Code
#include<bits/stdc++.h> #define il inline #define rg register const int maxn=1e5+5; char s[maxn],p[maxn]; int slen,plen,next[maxn]; il void Next(){ next[1]=0; for(rg i=2,j=0;i<=plen;++i){ while(j && p[i]!=p[j+1]) j=next[j]; if(p[i]==p[j+1]) ++j; next[i]=j; } } void KMP(){ int i=1,j=0,ans=0; for(rg i=1;i<=slen;++i){ while(j && s[i]!=p[j+1]) j=next[j]; if(s[i]==p[j+1]) ++j; if(j==plen){ printf("%d\n",i-j+1);j=next[j]; } } } int main(){ scanf("%s %s",s+1,p+1);slen=strlen(s+1),plen=strlen(p+1); Next(); KMP(); return 0; }
高斯消元
Miku's Code
#include<bits/stdc++.h> #define il inline #define rg register int il int read(){ char c=getchar();int x=0,f=1; while(c<48){ if(c=='-')f=-1;c=getchar(); } while(c>47){ x=(x<<3)+(x<<1)+(c^48);c=getchar(); } return x*f; } int n,y; double a[114][514]; void Guass(){ for(rg i=1;i<=n;++i){ y=i; while(a[y][i]==0 && y<=n) ++y; if(y==n+1) return printf("No Solution"),void(); for(rg j=1;j<=n+1;++j) std::swap(a[i][j],a[y][j]); double k=a[i][i]; for(rg j=1;j<=n+1;++j) a[i][j]/=k; for(rg j=1;j<=n;++j) if(i!=j){ double ji=a[j][i]; for(rg q=1;q<=n+1;++q) a[j][q]-=ki*a[i][q]; } } } int main(){ n=read(); for(rg i=1;i<=n;++i) for(rg j=1;j<=n+1;++j) scanf("%lf",&a[i][j]); Guass(); for(rg i=1;i<=n;++i) printf("%.2f\n",a[i][n+1]); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!