邻接表
const int MAX_N=100;
const int MAX_M=10000;
struct edge{
int v,next;
int len;
}E[MAX_M];
int p[MAX_N],eid;
void init(){
memset(p,-1,sizeof(p));
eid=0;
}
void insert(int u,int v,int len){
E[eid].v=v;
E[eid].len=len;
E[eid].next=p[u];
p[u]=eid++;
}
树叶子节点个数
int cnt[MAX_N];//统计结果
void dfs(int u){
vst[u]=true;
bool is_leaf=true;
for(int i=p[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(!vst[v]){
dfs(v);
is_leaf=false;
cnt[u]+=cnt[v];
}
}
if(is_leaf){
cnt[u]=1;
}
}
树的三种遍历方式
int lch[MAX_N],rch[MAX_N];
void preorder(int u){
cout<<"visting"<<u<<endl;
if(lch[u])preorder();
if(rch[u])preorder();
}
dijkstra算法
void dij(){
memset(dis,0x3f,sizeof(dis));
memset(mark,false,sizeof(mark));
mark[1]=true;int now=1;dis[1]=0;
for(int i=1;i<n;i++){
int mn=inf;
for(int i=p[now];i+1;i=E[i].next){
int v=E[i].v;
if(dis[v]>dis[now]+E[i].len){
dis[v]=dis[now]+E[i].len;
}
}
for(int i=2;i<=n;i++){
if(mark[i])continue;
if(dis[i]<mn){
mn=dis[i];
now=i;
}
}
mark[now]=true;
}
}
spfa算法
bool inq[MAX_N];
int d[MAX_N];
void spfa(int s){
memset(inq,false,sizeof(inq));
memset(d,0x3f,sizeof(d));
d[s]=0;
inq[s]=true;
queue<int>q;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
inq[u]=false;
for(int i=p[u];i+1;i=E[i].next){
int v=E[i].v;
if(d[u]+E[i].len<d[v]){
d[v]=d[u]+E[i].len;
if(!inq[v]){
q.push(v);
inq[v]=true;
}
}
}
}
}
floyd算法
void floyd(){
for(int k=0;k<n;++k){
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
if(G[i][k]+G[k][j]<G[i][j]){
G[i][j]=G[i][k]+G[k][j];
}
}
}
}
}
kruskal最短路径核心代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N=100000;
const int MAX_M=100000;
struct edge{
int u,v,w;
bool operator <(const edge &a)const{
return w<a.w;
}
}e[MAX_M];
int fa[MAX_N],n,m;
int get(int x){
if(fa[x]==x){
return fa[x];
}
return fa[x]=get(fa[x]);
}
int main() {
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>e[i].u>>e[i].v>>e[i].w;
}
sort(e,e+m);
for(int i=1;i<=n;i++){
fa[i]=i;
}
int sum=0;
for(int i=0;i<m;i++){
int x=get(e[i].u),y=get(e[i].v);
if(x!=y){
fa[x]=y;
sum+=e[i].w;
}
}
cout<<sum<<endl;
return 0;
}
倍增算法找最近公共祖先
#include <iostream>
#include<string.h>
using namespace std;
const int MAX_N=100000;
const int MAX_M=1000000;
struct edge{
int v,next;
}E[MAX_M];
int p[MAX_N],eid;
void init(){
memset(p,-1,sizeof(p));
eid=0;
}
void insert(int u,int v){
E[eid].v=v;
E[eid].next=p[u];
p[u]=eid++;
}
int d[MAX_N],fa[MAX_N][20];
void dfs(int u){
for(int i=p[u];i+1;i=E[i].next){
if(d[E[i].v]==-1){
d[E[i].v]=d[u]+1;
fa[E[i].v][0]=u;
dfs(E[i].v);
}
}
}
int lca(int x,int y){
int i,j;
if(d[x]<d[y]){
swap(x,y);
}
for(i=0;(1<<i)<=d[x];i++);
--i;
for( j=i;j>=0;j--){
if(d[x]-(1<<j)>=d[y]){
x=fa[x][j];
}
}
if(x==y){
return x;
}
for( j=i;j>=0;j--){
if(fa[x][j]!=fa[y][j]){
x=fa[x][j];
y=fa[y][j];
}
}
return fa[x][0];
}
int main() {
int n;
init();
cin>>n;
for(int i=0;i<n-1;++i){
int u,v;
cin>>u>>v;
insert(u,v);
insert(v,u);
}
memset(d,-1,sizeof(d));
dfs(1);
for(int level=1;(1<<level)<=n;level++){
for(int i=1;i<=n;i++){
fa[i][level]=fa[fa[i][level-1]][level-1];
}
}
int q;
cin>>q;
while(q--){
int a,b;
cin>>a>>b;
cout<<lca(a,b)<<endl;
}
return 0;
}
topo排序
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int MAX_N=100;
const int MAX_M=10000;
struct edge{
int v,next;
int len;
}E[MAX_M];
int p[MAX_N],eid;
void init(){
memset(p,-1,sizeof(p));
eid=0;
}
void insert(int u,int v){
E[eid].v=v;
E[eid].next=p[u];
p[u]=eid++;
}
int n,m;
int indegree[MAX_N];
void topo(){
queue<int>q;
for(int i=1;i<=n;i++){
if(indegree[i]==0){
q.push(i);
}
}
while(!q.empty()){
int now=q.front();
cout<<now<<endl;
q.pop();
for(int i=p[now];i+1;i=E[i].next){
int v=E[i].v;
indegree[v]--;
if(indegree[v]==0){
q.push(v);
}
}
}
}
int main() {
init();
memset(indegree,0,sizeof(indegree));
cin>>n>>m;
for(int i=0;i<m;++i){
int u,v;
cin>>u>>v;
insert(u,v);
++indegree[v];
}
topo();
return 0;
}
欧拉路径
//无向图欧拉路径
const int MAX_N=100;
int mat[MAX_N][MAX_N];
int match[MAX_N];//表示顶点剩余的度
int n;//顶点个数
void solve(int u){
if(match[u]>0){
for(int i=1;i<n;++i){
if(mat[u][i]){
mat[u][i]--;
mat[i][u]--;
solve(i);
}
}
}
cout<<"visiting"<<u<<endl;
}
//有向图欧拉路径
const int MAX_N=100;
const int MAX_M=10000;
int mat[MAX_N][MAX_N];
int match[MAX_N];//表示顶点剩余的度
int n;//顶点个数
int stk[MAX_M],top=0;//用数组来模拟一个栈
void solve(int u){
if(match[u]>0){
for(int i=1;i<n;++i){
if(mat[u][i]){
mat[u][i]--;
mat[i][u]--;
solve(i);
}
}
}
stk[top++]=u;
}
tarjan模板:
#include<bits/stdc++.h>
#define MAX 10005
using namespace std;
int dfn[MAX],low[MAX],inst[MAX],belong[MAX],st[MAX],tot,sum,top;
vector<int>G[MAX];
void tarjan(int u)
{
int v;
dfn[u]=low[u]=++tot;
st[++top]=u;
inst[u]=1;
for(int i=0;i<G[u].size();i++)
{
v=G[u][i];
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]); //找出父子结点对应关系
}
else if(inst[v]) //如果访问过,并且还在栈里
low[u]=min(low[u],dfn[v]); //连接父子结点对应关系
}
if(dfn[u]==low[u]) //找到强连通分量子树里的最小根
{
sum++; //强连通分量个数sum
do{
v=st[top--];
belong[v]=sum;
inst[v]=0;
}while(u!=v);
}
}
void init()
{
for(int i=0;i<MAX;i++)
G[i].clear();
top=-1;
sum=tot=0;
memset(inst,0,sizeof(inst));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
}
int main()
{
int n,m,x,y,i;
while(cin>>n>>m)
{
init();
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
}
for(i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
}
for(int i=1;i<=sum;++i){
cout<<"block "<<i<<": ";
for(int j=1;j<=n;++j){
if(belong[j]==i){
cout<<j<<" ";
}
}
cout<<endl;
}
return 0;
}
//