1.floyd(最短路)
读入时注意筛选最小边
void floyd()
{
for(int u=0;u<=n;u++)
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
dp[i][j]=min(dp[i][j],dp[i][u]+dp[u][j]);
}
2.dijkstra(最短路)
函数调用前记得初始化
核心思想是从起点发散,每次找到下一个任意未标记点的最短路
如A——>C为4,A——>B为2,则选取A——>B这条路径,并将B点标记,更新路径,再从B点发散寻找下一点
int dis[maxn];
int vis[maxn];
int a[maxn][maxn];
void dij(int start)
{
for(int i=1;i<=n;i++)
dis[i]=a[start][i];
vis[s]=1;
for(int i=1;i<=n;i++)
{
int k=0;//k取一个无法到达值
for(int j=1;i<=n;j++)
if(vis[j]==0&&(k==0||dis[k]>dis[j])
k=j;
for(int j=1;j<=n;j++)
if(vis[j]==0&&dis[j]>dis[k]+a[k][j])
dis[j]=dis[k]+a[k][j];
}
}
3.dijkstra的队列优化写法
vector是从0开始的
struct node
{
ll to,value;
node(ll to1,ll value1):to(to1),value(value1){}//数据读入
friend bool operator<(node a, node b)
{
return a.value>b.value;
}
};
vector<node> v[maxn];//v[i]的i记录起点,v[i].to记录终点;
ll dis[maxn];//记录最短路
priority_queue <node> que;
void dij(ll s)//起点
{
while(!que.empty()) que.pop();//初始化
for(int i=0;i<=n;i++)
{
dis[i]=inf;
}
dis[s]=0;//初始化
que.push(node(s,0));//将起点送入优先队列
while(!que.empty())
{
node tmp=que.top();
que.pop();
if(tmp.value > dis[tmp.to]) continue;
for(ll i=0;i<(ll) v[tmp.to].size();i++)
{
ll to=v[tmp.to][i].to;
ll val=v[tmp.to][i].value;
if(dis[to]>dis[tmp.to]+val)
{
dis[to]=dis[tmp.to]+val;
que.push(node(to,dis[to]));
}
}
}
}
4.spfa
5.链式前向星(对边的记录)
初始化时head要赋值为-1
struct Edge
{
int to,w,next;
}E[maxn];
int head[maxn];
int tot;
inline void addEdge(int u,int v,int w)
{
Edge[tot].to=v;
Edge[tot].w=w;
Edge[tot].next=head[u];
head[u]=tot++;
}
void solve(int x)
{
for(int i=head[x];~i;i=E[i].next)//i=-1时结束循环
//something...
}
6.最小生成树(prime)
和dijkstra非常像,只有一个判断语句不同,dij要保证每个点和单源点相连,而prime只要保证连通且当前路径最小即可
struct node
{
int to;
int val;
};
vector<node> e[maxn];
int dis[maxn];
int vis[maxn];
int prime(int n)
{
memset(vis,0,sizeof(vis));
int ans=0;
dis[1]=0;
vis[1]=1;
for(int i=0;i<e[1].size();i++)
{
dis[e[1][i].to]=e[1][i].val;
}
for(int point=2;point<=n;point++)
{
int minn=inf;
int k=0;
for(int i=1;i<=n;i++)
{
if(vis[i]==0&&minn>dis[i])
{
minn=dis[i];
k=i;
}
}
vis[k]=1;
ans+=minn;
for(int i=0;i<e[k].size();i++)
{
if(dis[e[k][i].to]>e[k][i].val)
{
dis[e[k][i].to]=e[k][i].val;
}
}
}
return ans;
}
7.并查集
int root[maxn];
int FIND(int x)
{
return root[x]==x?x:root[x]=FIND(root[x]);
}
void hb(int x,int y)//合并
{
int xx=FIND(x);
int yy=FIND(y);
if(xx!=yy)
{
root[xx]=yy;
}
}
8.最小生成树(kruskal)
使用时要在先对对边进行排序
int root[maxn];
int FIND(int x)
{
return root[x]==x?x:root[x]=FIND[x];
}
struct Edge
{
int x,y,w;
friend bool operator<(Edge a,Edge b)
{
return a.w<b.w;
}
}e[maxn];
int kruskal()
{
int ans=0;
for(int i=1;i<=n;i++)
root[i]=i;
for(int i=1;i<=m;i++)
{
int a=FIND(e[i].x),b=FIND(e[i].y);
if(a!=b)
{
root[a]=b;
ans+=e[i].w;
}
}
return ans;
}
8.欧拉通路、回路
9.二分图染色判断
int vis[maxn];
int head[maxn];
int color[maxn];//使用^运算 0未染色,2为一种颜色,3为另外一种颜色
/*
也可 1为黑,2为白 用3-color来使颜色交替变换
*/
int tot;
struct node
{
int to,next;
}E[maxn];
void adde(int x,int y)
{
E[tot].to=y;
E[tot].next=head[x];
head[x]=tot++;
}
void add(int x,int y)
{
adde(x,y);
adde(y,x);
}
void init()
{
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
tot=0;
memset(color,0,sizeof(color));
}
bool dfs(int past,int y)
{
color[past]=y;
for(int i=head[past];~i;i=E[i].next)
{
int now=E[i].to;//now 为past的邻接点
if(color[past]==color[now])//判断past和now染色是否相同
return false;
if(color[now]==0&&!dfs(now,y^1))//past的邻接点未染色,则进行递归,直到对应的点完成染色
return false;
}
return true;//表示没有搜索到有冲突的颜色节点,二分图成立
}
bool jungle()//judge
{
for(int i=1;i<=n;i++)
{
if(color[i]==0)//确保所有点完成遍历染色(可能有多个连通图)
/*
如hdu4751,建边是对互相不认识的人建边,当所有人都认识的时候没有边,此时每个图仅有一个点,
需要做的就是对每个点(连通图)染色
*/
if(dfs(i,2)==false)
{
return false
}
}
return true;
}
10.二分图最大匹配(匈牙利算法)
int vis[maxn];
int head[maxn];
int match[maxn];//match[i]=j i与j对应匹配,i为右边被匹配点
int tot;
struct node
{
int to,next;
}E[maxn];
void adde(int x,int y)
{
E[tot].to=y;
E[tot].next=head[x];
head[x]=tot++;
}
void add(int x,int y)
{
adde(x,y);
adde(y,x);
}
bool dfs(int x,int ti) //ti记录次数
{
if(vis[x]==ti) return false;
vis[x]=ti;
for(int i=head[x];~i;i=E[i].next)
{
int tmp=E[i].to;
if(match[tmp]==0||dfs(match[tmp],ti))
/*
tmp点未匹配时候,tmp点与当前点匹配
tmp点已经匹配,找到之前匹配点,对其进行再匹配处理,若能成功,则将tmp点与当前点匹配
*/
{
match[tmp]=x;
return true;
}
}
return false;
}
int solve()
{
int ans=0;
for(int i=1;i<=n;i++)
{
if(dfs(i,i)) ans++;
}
return ans;
}
void init()
{
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
tot=0;
memset(color,0,sizeof(match));
}
11.拓扑排序
https://blog.csdn.net/qq_41713256/article/details/80805338
while(!q.empty())
{
int tmp=q.front();
q.pop();
int len=v[tmp].size();
for(int i=0;i<len;i++)
{
if(--degree[v[tmp][i]]==0)
{
q.push(v[tmp][i]);
}
}
}