一. 树与图的深度优先遍历(846. 树的重心 - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 201000;
const int M = 2 * N;
int idx,e[M],h[N],ne[M];
int n;
bool str[M];
int ans=N;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int dfs(int u)
{
str[u]=true;
int sum=1,res=0;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(!str[j])
{
int s=dfs(j);
res=max(res,s);
sum+=s;
}
}
res=max(res,n-sum);
ans=min(ans,res);
return sum;
}
int main()
{
cin>>n;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++)
{
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs(1);
cout<<ans<<'\n';
return 0;
}
二.树与图的广度优先遍历(847. 图中点的层次 - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 101000;
int n,m;
int e[N],ne[N],h[N],idx;
int d[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int bfs()
{
queue<int> q;
memset(d,-1,sizeof d);
q.push(1);
d[1]=0;
while(q.size())
{
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(d[j]==-1)
{
d[j]=d[t]+1;
q.push(j);
}
}
}
return d[n];
}
int main()
{
cin>>n>>m;
int a,b;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++)
{
cin>>a>>b;
add(a,b);
}
cout<<bfs()<<'\n';
return 0;
}
三.拓扑排序(848. 有向图的拓扑序列 - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 101000;
int n,m;
int e[N],ne[N],h[N],idx;
int d[N],q[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool topsort()
{
int hh=0,tt=-1;
for(int i=1;i<=n;i++)
{
if(!d[i])
{
q[++tt]=i;
}
}
while(hh<=tt)
{
int t=q[hh++];
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
d[j]--;
if(!d[j])
{
q[++tt]=j;
}
}
}
return tt==n-1;
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
add(a,b);
d[b]++;
}
if(topsort())
{
for(int i=0;i<n;i++)
{
cout<<q[i]<<" ";
}
cout<<'\n';
}else{
cout<<"-1\n";
}
return 0;
}
四.求最短路
1.Dijkstra 朴素算法 O(n^2) (849. Dijkstra求最短路 I - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int n,m;
int g[N][N],d[N];
bool str[N];
int Dijlstra()
{
memset(d,0x3f,sizeof d);
d[1]=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!str[j]&&(t==-1||d[t]>d[j]))
{
t=j;
}
}
for(int j=1;j<=n;j++)
{
d[j]=min(d[j],d[t]+g[t][j]);
}
str[t]=true;
}
if(d[n]==0x3f3f3f3f) return -1;
else return d[n];
}
int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g);
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
g[x][y]=min(g[x][y],z);
}
cout<<Dijlstra()<<'\n';
return 0;
}
2.堆优化版的Dijkstra算法 O(mlogn)
(850. Dijkstra求最短路 II - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int ,int > PII;
const int N = 201000;
int n,m;
int e[N],h[N],ne[N],idx,w[N];
int d[N];
bool str[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int Dijkstra()
{
priority_queue<PII, vector<PII>, greater<PII>> heap;
memset(d,0x3f,sizeof d);
d[1]=0;
heap.push({0,1});
while(heap.size())
{
auto t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(str[ver]) continue;
str[ver]=true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(d[j]>d[ver]+w[i])
{
d[j]=d[ver]+w[i];
heap.push({d[j],j});
}
}
}
if(d[n]==0x3f3f3f3f) return -1;
else return d[n];
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
cout<<Dijkstra()<<'\n';
return 0;
}
3.bellman-ford算法 O(nm)(853. 有边数限制的最短路 - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 201000;
int n,m,k;
int d[N],last[N];
struct Edge
{
int a,b,w;
}edges[N];
void bellman_ford()
{
memset(d,0x3f,sizeof d);
d[1]=0;
for(int i=0;i<k;i++)
{
memcpy(last,d,sizeof d);
for(int j=0;j<m;j++)
{
auto e=edges[j];
d[e.b]=min(d[e.b],last[e.a]+e.w);
}
}
}
int main()
{
cin>>n>>m>>k;
for(int i=0;i<m;i++)
{
int a,b,w;
cin>>a>>b>>w;
edges[i]={a,b,w};
}
bellman_ford();
if(d[n]>0x3f3f3f3f/2) cout<<"impossible\n";
else cout<<d[n]<<'\n';
return 0;
}
4.SFPA算法O(m--nm)(851. spfa求最短路 - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 201000;
int n,m;
int e[N],h[N],ne[N],w[N],idx;
int d[N];
bool str[N];
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void spfa()
{
memset(d,0x3f,sizeof d);
queue<int>q;
d[1]=0;
q.push(1);
str[1]=true;
while(q.size())
{
auto t=q.front();
q.pop();
str[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(d[j]>d[t]+w[i])
{
d[j]=d[t]+w[i];
if(!str[j])
{
q.push(j);
str[j]=true;
}
}
}
}
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
while(m--)
{
int a,b,c;
scanf("%d%d%d", &a, &b, &c);
add(a,b,c);
}
spfa();
if(d[n]==0x3f3f3f3f) cout<<"impossible\n";
else cout<<d[n]<<'\n';
return 0;
}
5.852. spfa判断负环 - AcWing题库
#include <bits/stdc++.h>
using namespace std;
const int N = 201000;
int n,m;
int e[N],h[N],ne[N],w[N],idx;
int d[N],cnt[N];
bool str[N];
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
int spfa()
{
queue<int>q;
for(int i=1;i<=n;i++)
{
str[i]=true;
q.push(i);
}
while(q.size())
{
auto t=q.front();
q.pop();
str[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(d[j]>d[t]+w[i])
{
d[j]=d[t]+w[i];
cnt[j]=cnt[t]+1;
if(cnt[j]>=n) return false;
if(!str[j])
{
q.push(j);
str[j]=true;
}
}
}
}
return true;
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
while(m--)
{
int a,b,c;
scanf("%d%d%d", &a, &b, &c);
add(a,b,c);
}
if(spfa()) cout<<"No";
else cout<<"Yes";
return 0;
}
6.Floyd算法O(n^3) (854. Floyd求最短路 - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 210, INF = 1e9;
int n, m, Q;
int d[N][N];
void floyd()
{
for (int k = 1; k <= n; k ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
int main()
{
scanf("%d%d%d", &n, &m, &Q);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
if (i == j) d[i][j] = 0;
else d[i][j] = INF;
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
d[a][b] = min(d[a][b], c);
}
floyd();
while (Q -- )
{
int a, b;
scanf("%d%d", &a, &b);
int t = d[a][b];
if (t > INF / 2) puts("impossible");
else printf("%d\n", t);
}
return 0;
}
五.求最小生成树
1.Prim算法 (858. Prim算法求最小生成树 - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 510,INF=0x3f3f3f3f;
int n,m;
int d[N],g[N][N];
bool str[N];
int prim()
{
memset(d,INF,sizeof d);
int res=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!str[j]&&(t==-1||d[t]>d[j]))
{
t=j;
}
}
if(i&&d[t]==INF) return INF;
if(i) res+=d[t];
str[t]=true;
for(int j=1;j<=n;j++) d[j]=min(d[j],g[t][j]);
}
return res;
}
int main()
{
cin>>n>>m;
memset(g,INF,sizeof g);
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=g[b][a]=min(g[a][b],c);
}
int tt=prim();
if(tt==INF) cout<<"impossible";
else cout<<tt<<'\n';
return 0;
}
2.Kruskalw算法(859. Kruskal算法求最小生成树 - AcWing题库)
#include <bits/stdc++.h>
using namespace std;
const int N = 201000;
int n,m;
int p[N];
struct Node
{
int x,y,z;
}st[N];
bool cmp(Node a,Node b)
{
return a.z<b.z;
}
int find(int x)
{
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int Kruskal()
{
int res=0,cnt=0;
for(int i=0;i<m;i++)
{
int a=st[i].x,b=st[i].y,c=st[i].z;
a=find(a),b=find(b);
if(a!=b)
{
p[a]=b;
res+=c;
cnt++;
}
}
if(cnt<n-1) return -1;
return res;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) p[i]=i;
for(int i=0;i<m;i++)
{
cin>>st[i].x>>st[i].y>>st[i].z;
}
sort(st,st+m,cmp);
int tt=Kruskal();
if(tt==-1) cout<<"impossible\n";
else cout<<tt<<'\n';
return 0;
}
六.染色法判定二分图(AcWing 860. 染色法判定二分图 - AcWing)
#include <bits/stdc++.h>
using namespace std;
const int N = 201000;
int n,m;
int color[N];
int e[N],ne[N],h[N],idx;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool dfs(int u,int c)
{
color[u]=c;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(!color[j])
{
if(!dfs(j,3-c)) return false;
}
else if(color[j]==c) return false;
}
return true;
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
bool str=true;
for(int i=1;i<=n;i++)
{
if(!color[i])
{
if(!dfs(i,1))
{
str=false;
break;
}
}
}
if(str) cout<<"Yes\n";
else cout<<"No\n";
return 0;
}
七.匈牙利算法(861. 二分图的最大匹配 - AcWing题库)
#include <bits/stdc++.h>
const int N = 510,M=100100;
int n1,n2,m;
int e[M],ne[M],h[M],idx;
bool str[N];
int match[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool find(int x)
{
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
if(!str[j])
{
str[j]=true;
if(match[j]==0||find(match[j]))
{
match[j]=x;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d %d %d", &n1, &n2, &m);
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
scanf("%d %d", &a, &b);
add(a,b);
}
int res=0;
for(int i=1;i<=n1;i++)
{
memset(str,false,sizeof str);
if(find(i)) res++;
}
printf("%d",res);
return 0;
}
(制作不易,若要收藏请留下小红心)