- Flyod
for(int k=1;k<=n;k++){//代表中转顶点从1到n
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dis[i][j]>dis[i][k]+dis[k][j]){
dis[i][j]=dis[i][k]+dis[k][j];
- Dijkstra
void dijkstra(int u){
int vis[M]={0};
vis[u]=1;
for(int i=0;i<n;++i){
int mi=0x3f3f3f3f,v=-1;
for(int j=0;j<n;++j){
if(!vis[j]&&mi>e[u][j])
mi=e[u][v=j];
}
if(v==-1) break;
vis[v]=1;
for(int j=0;j<n;++j){
if(vis[j])
continue;
if(e[u][j]>e[u][v]+e[v][j]){
e[u][j]=e[u][v]+e[v][j];
}
}
}
}
或者用dist数组存,没有初始化是因为,第一次找到的最小值只可能是源点,所以第一遍之后就相当于初始化了
int dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
for(int i=0;i<n-1;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
if(!st[j]&&(t==-1||dist[j]<dist[t]))
t=j;
st[t]=true;
for(int j=1;j<=n;j++)
dist[j]=min(dist[j],dist[t]+g[t][j]);
}
if(dist[n]==0x3f3f3f3f) return -1;
return dist[n];
}
或者链式前向星
void add(int u,int v,int w){
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void dijkstra(int s){
int vis[M]={0};
memset(dist,0x3f,sizeof(dist));
dist[s]=0;
for(int i=0;i<n;++i){
int mn=INT_MAX,u=-1;
for(int j=0;j<n;++j){
if(!vis[j] && dist[j]<mn){
mn=dist[j];
u=j;
}
}
if(u==-1) break;
vis[u]=1;
for(int j=head[u];~j;j=edge[j].next){
int v=edge[j].v;
if(dist[v]>dist[u]+edge[j].w){
dist[v]=dist[u]+edge[j].w;
}
}
}
}
- 优化版的Dijkstra
typedef pair<int,int>PII;
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
priority_queue<PII,vector<PII>,greater<PII>>heap;
heap.push({0,1});
while(heap.size())
{
auto t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(st[ver]) continue;
st[ver]=true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>distance+w[i])
{
dist[j]=distance+w[i];
heap.push({dist[j],j});
}
}
}
if(dist[n]==0x3f3f3f) return -1;
return dist[n];
}
- Bellman-Ford
for(int k=1; k<=n-1; ++k) { //进行n-1次松弛
int f=1; // 简单优化,如果没有松弛就表明结束了
for(int i=1; i<=m; ++i) { // 枚举每一条边
if(dis[v[i]]>dis[u[i]]+w[i]) { // 尝试对每一条边松弛
dis[v[i]]=dis[u[i]]+w[i];
f=0;
}
}
if(f) break;
}
//检测负权回路
int f=1;
for(int i=1; i<=m; ++i) {
if(dis[v[i]]>dis[u[i]]+w[i]) {
f=0;
break;
}
}
- SPFA
void spfa (int u)
{
int v, w, i;
for (i = 1; i <= n; i++) //对于从1到n的编号
dist[i] = inf, inq[i] = false;
dist[u] = 0;
queue<int> q;
q.push (u);
inq[u] = true;
while (!q.empty())
{
u = q.front();
q.pop();
inq[u] = false;
for (i = pre[u]; i != -1; i = e[i].next)
{
w = e[i].w;
v = e[i].v;
if (dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
if (!inq[v])
{
q.push (v);
if(++nums[v]>n) //说明有负圈
return false;
inq[v] = true;
}
}
}
// 之前我见到过一种在这里判断负圈的方法,但是当时只是看了一眼没有记住,如果有哪位朋友有这种方法麻烦给我说一下
}
}
- Prim
int e[1005][1005];
void Prim(int u)
{
int vis[1005]={0},cnt=0;
vis[u]=1;
for(int i=1;i<=n;++i){
int min=maxn,v=-1;
for(int j=1;j<=n;++j){
if(!vis[j] && min>e[u][j]){
min=e[u][j];
v=j;
}
}
if(v==-1)
break;
sum+=e[u][v];
vis[v]=1;
cnt++;
for(int j=1;j<=n;++j){
if(vis[j]) continue;
if(e[u][j]>e[v][j]){
e[u][j]=e[v][j];
}
}
}
if(cnt!=n) // 图不连通
return ;
// for(int i=1;i<=n;++i){
// if(!vis[i]){
// cout << "-1";
// return ;
// }
// }
cout << sum;
}
- Kruskal
struct edge{
int u,v;
int length;
bool operator<(const edge a)const{
return length<a.length;
}
}e[3005];
int n,m;
int pre[3005];
int find(int x)
{
return pre[x]==x?x:pre[x]=find(pre[x]);
}
void Kruskal()
{
int cnt=1,sum=0;
sort(e,e+m);
for(int i=0;i<m;++i){
if(find(e[i].u)!=find(e[i].v)){
cnt++;
sum+=e[i].length;
pre[find(e[i].u)]=find(e[i].v);
}
}
if(cnt<n)
cout << "-1\n";
else
cout << sum;
}
- 二分图,匈牙利算法
bool find(int x) {
int i,j;
for (j=1; j<=m; j++) {
if (line[x][j]==true && used[j]==false) {
used[j]=1;
if (girl[j]==0 || find(girl[j])) {
girl[j]=x;
return true;
}
}
}
return false;
}
int main() {
for (i=1; i<=n; i++) {
memset(used,0,sizeof(used));
if find(i) all+=1;
}
}
- 割顶和桥
vector<int> g[maxn];
bool iscut[maxn];
int pre[maxn],low[maxn],dfs_clock=0;
int dfs(int u,int fa) {
int lowu=pre[u]= ++dfs_clock;
int child=0;
for(int i=0;i<g[u].size();++i){
int v=g[u][i];
if(!pre[v]){
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u]) // 等号去了 是求桥
iscut[u]=true;
}
else if(pre[v]<pre[u] && v!=fa)
lowu=min(lowu,pre[v]);
}
if(fa<0 && child==1)
iscut[u]=false;
low[u]=lowu;
return lowu;
}
觉得我的没有介绍的话也可以查看这篇:这里