最短路Dijkstra,spfa,图论二分图算法AYIT---ACM训练(模板版)


文章目录

  • 前言
  • [A - Dijkstra Algorithm](#A - Dijkstra Algorithm)
    • [0x00 算法题目](#0x00 算法题目)
    • [0x01 算法思路](#0x01 算法思路)
    • [0x02 代码实现](#0x02 代码实现)
  • [B - 最长路](#B - 最长路)
    • [0x00 算法题目](#0x00 算法题目)
    • [0x01 算法思路](#0x01 算法思路)
    • [0x02 代码实现](#0x02 代码实现)
  • [C - 二分图最大匹配](#C - 二分图最大匹配)
    • [0x00 算法题目](#0x00 算法题目)
    • [0x01 算法思路](#0x01 算法思路)
    • [0x02 代码实现](#0x02 代码实现)
  • [D - 搭配飞行员](#D - 搭配飞行员)
    • [0x00 算法题目](#0x00 算法题目)
    • [0x01 算法思路](#0x01 算法思路)
    • [0x02 代码实现](#0x02 代码实现)
  • [E - The Perfect Stall](#E - The Perfect Stall)
    • [0x00 算法题目](#0x00 算法题目)
    • [0x01 算法思路](#0x01 算法思路)
    • [0x02 代码实现](#0x02 代码实现)
  • [F - Asteroids](#F - Asteroids)
    • [0x00 算法题目](#0x00 算法题目)
    • [0x01 算法思路](#0x01 算法思路)
    • [0x02 代码实现](#0x02 代码实现)
  • [G - Til the Cows Come Home](#G - Til the Cows Come Home)
    • [0x00 算法题目](#0x00 算法题目)
    • [0x01 算法思路](#0x01 算法思路)
    • [0x02 代码实现](#0x02 代码实现)
  • [H - 拓扑排序](#H - 拓扑排序)
    • [0x00 算法题目](#0x00 算法题目)
    • [0x01 算法思路](#0x01 算法思路)
    • [0x02 代码实现](#0x02 代码实现)
  • 总结

前言

最短路Dijkstra,spfa,图论二分图算法AYIT---ACM训练(模板版)

A --- Dijkstra

B --- spfa/Dijkstra

C --- 二分图

D --- 二分图

E --- 二分图

F --- 二分图

G --- Dijkstra

H --- Topsort


A - Dijkstra Algorithm

0x00 算法题目

0x01 算法思路

Dijkstra算法基础模板题

💬 模板演示:

cpp 复制代码
int dijkstra()
{
    memset(dist,0x3f,sizeof dist);

    dist[1]=0;

    for(int i=0;i<n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
        {
            if(!st[j] && (t==-1 || dist[t] > dist[j]))
                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];

}

0x02 代码实现

朴素版本Dijkstra:

💬 代码演示:

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 510;
int g[N][N];
bool st[N];
int dist[N];
int n,s,f;

int dijkstra()
{
	memset(dist,0x3f,sizeof dist);
	dist[s]=0;
	
	for(int i=0;i<n;i++)
	{
		int t=-1;
		for(int j=1;j<=n;j++)
			if(!st[j] && (t==-1 || dist[t] > dist[j]))
				t=j;
		
		st[t]=true;
		for(int j=1;j<=n;j++)
			dist[j]=min(dist[j],dist[t]+g[t][j]);
	}
	if(dist[f]==0x3f3f3f3f) return -1;
	return dist[f];
}

int main()
{
	cin>>n>>s>>f;
	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			int x;
			cin>>x;
			if(x==-1) g[i][j]=0x3f3f3f3f;
			else g[i][j]=x;
		}
	}
	
	int t =dijkstra();
	cout<<t<<endl;
	
	return 0;
}

🚩 运行结果:

spfa算法:

💬 代码演示:

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;
const int N=110,M=110*110;
int n,s,f;
bool st[N];
int h[N],w[M],ne[M],e[M],idx;
int dist[N];

void add(int a,int b,int c)
{
	e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

int spfa()
{
	memset(dist,0x3f,sizeof dist);
	dist[s]=0;
	queue<int> q;
	q.push(s);
	while(q.size())
	{
		int t = q.front();
		q.pop();
		st[t]=false;
		
		for(int i=h[t];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(dist[j] > dist[t] + w[i])
			{
				dist[j]=dist[t]+w[i];
				if(!st[j])
				{
					q.push(j);
					st[j]=true;
				}
			}
		}
	}
	if(dist[f]==0x3f3f3f3f) return -1;
	else return dist[f];
}

int main()
{
	cin>>n>>s>>f;
	memset(h,-1,sizeof h);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			int x;
			cin>>x;
			//if(x==-1) continue;
			if(x>0) add(i,j,x);
		}
	}
	cout<<spfa()<<endl;
	
	return 0;
}

🚩 运行结果:

B - 最长路

0x00 算法题目

0x01 算法思路

spfa算法基础模板题

💬 模板演示:

cpp 复制代码
int spfa()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;

    queue<int> q;
    q.push(1);

    while(q.size())
    {
        auto t = q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j = e[i];
            if(dist[j] > dist[t]+w[i])
            {
                dist[j]=dist[t]+w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    return dist[n];
}

0x02 代码实现

spfa算法:

💬 代码演示:

cpp 复制代码
#include<bits/stdc++.h>
#define endl '\n'

using namespace std;
const int N = 1510,INF = 0x3f3f3f3f;
int n,m;
int dist[N];
int g[N][N];
queue<int> q;

void spfa()
{
	memset(dist,-1,sizeof dist);
	dist[1]=0;
	q.push(1);
	while(!q.empty())
	{
		int t = q.front();
		q.pop();
		for(int j=1;j<=n;j++)
		{
			if(g[t][j] && dist[j] < dist[t] + g[t][j])
			{
				dist[j] = dist[t] + g[t][j];
				q.push(j);
			}
		}
	}
	
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		g[a][b]=max(g[a][b],c);
	}
	spfa();
	cout<<dist[n]<<endl;
	return 0;
}

🚩 运行结果:

C - 二分图最大匹配

0x00 算法题目

0x01 算法思路

二分图模板题

💬 模板演示:

cpp 复制代码
//邻接表
bool find(int x)
{
    for (int i = h[x]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true;
            if (match[j] == 0 || find(match[j]))
            {
                match[j] = x;
                return true;
            }
        }
    }

    return false;
}
//邻接矩阵
bool find(int x)
{
    for(int i=0;i<g[x].size();++i)
    {
        int j = g[x][i];
        if(!st[j])
        {
            st[j]=true;
            if(match[j]==0 || find(match[j]))
            {
                match[j]=x;
                return true;
            }
        }
    }
    return false;
}

0x02 代码实现

💬 代码演示:

cpp 复制代码
#include<iostream>
#include<cstring>

using namespace std;

const int N = 510,M=5e4+10;
int n,m,q;
int h[N],e[M],ne[M],idx;
int match[N];
bool st[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(!st[j])
		{
			st[j]=true;
			if(match[j]==0 || find(match[j]))
			{
				match[j]=x;
				return true;
			}
		}
	}
	return false;
}

int main()
{
	cin>>n>>m>>q;
	memset(h,-1,sizeof h);
	while(q--)
	{
		int u,v;
		cin>>u>>v;
		add(u,v);
	}
	int res=0;
	for(int i=1;i<=n;i++)
	{
		memset(st,false,sizeof st);
		if(find(i)) res++;
	}
	cout<<res<<endl;
	
	return 0;
}

🚩 运行结果:

D - 搭配飞行员

0x00 算法题目

0x01 算法思路

二分图模板题

💬 模板演示:

cpp 复制代码
//邻接表
bool find(int x)
{
    for (int i = h[x]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true;
            if (match[j] == 0 || find(match[j]))
            {
                match[j] = x;
                return true;
            }
        }
    }

    return false;
}
//邻接矩阵
bool find(int x)
{
    for(int i=0;i<g[x].size();++i)
    {
        int j = g[x][i];
        if(!st[j])
        {
            st[j]=true;
            if(match[j]==0 || find(match[j]))
            {
                match[j]=x;
                return true;
            }
        }
    }
    return false;
}

0x02 代码实现

💬 代码演示:

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>

using namespace std;
const int N = 110;

int n,m;
int map[N][N];
int match[N];
bool st[N];
vector<int> g[N];
bool find(int x)
{
	for(int i=0;i<g[x].size();++i)
	{
		int j = g[x][i];
		if(!st[j])
		{
			st[j]=true;
			if(match[j]==0 || find(match[j]))
			{
				match[j]=x;
				return true;
			}
		}
	}
	return false;
}

int main()
{
	scanf("%d %d",&n,&m);
	int a,b;
	while(cin>>a>>b)
	{
		g[a].push_back(b);
	}
	
	int res = 0;
	for(int i=1;i<=m;i++)
	{
		memset(st,false,sizeof st);
		if(find(i)) 
		{
			res++;
		}
	}
	
	cout<<res;
	
	return 0;
}

🚩 运行结果:

E - The Perfect Stall

0x00 算法题目

0x01 算法思路

二分图模板题

💬 模板演示:

cpp 复制代码
//邻接表
bool find(int x)
{
    for (int i = h[x]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true;
            if (match[j] == 0 || find(match[j]))
            {
                match[j] = x;
                return true;
            }
        }
    }

    return false;
}
//邻接矩阵
bool find(int x)
{
    for(int i=0;i<g[x].size();++i)
    {
        int j = g[x][i];
        if(!st[j])
        {
            st[j]=true;
            if(match[j]==0 || find(match[j]))
            {
                match[j]=x;
                return true;
            }
        }
    }
    return false;
}

0x02 代码实现

💬 代码演示:

cpp 复制代码
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
const int N = 510,M=5e4+10;
int n,m;
int match[N];
bool st[N];
vector<int> g[N];

bool find(int x)
{
	for(int i=0;i<g[x].size();++i)
	{
		int j = g[x][i];
		if(!st[j])
		{
			st[j]=true;
			if(match[j]==0 || find(match[j]))
			{
				match[j]=x;
				return true;
			}
		}
	}
	return false;
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		memset(st,false,sizeof st);
		memset(match,0,sizeof match);
		for(int i=1;i<=n;i++)
		{
			
			g[i].clear();
			int s;
			cin>>s;
			while(s--)
			{
				int q;
				cin>>q;
				g[i].push_back(q);
			}
		}
		int res=0;
		for(int i=1;i<=n;i++)
		{
			memset(st,false,sizeof st);
			if(find(i)) res++;
		}
		cout<<res<<endl;
	}
	
	return 0;
}

🚩 运行结果:

F - Asteroids

0x00 算法题目

0x01 算法思路

二分图模板题

💬 模板演示:

cpp 复制代码
//邻接表
bool find(int x)
{
    for (int i = h[x]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            st[j] = true;
            if (match[j] == 0 || find(match[j]))
            {
                match[j] = x;
                return true;
            }
        }
    }

    return false;
}
//邻接矩阵
bool find(int x)
{
    for(int i=0;i<g[x].size();++i)
    {
        int j = g[x][i];
        if(!st[j])
        {
            st[j]=true;
            if(match[j]==0 || find(match[j]))
            {
                match[j]=x;
                return true;
            }
        }
    }
    return false;
}

0x02 代码实现

💬 代码演示:

cpp 复制代码
#include<iostream>
#include<cstring>
using namespace std;
const int N = 510,M=5e4+10;
int n,m,q;
int h[N],e[M],ne[M],idx;
int match[N];
bool st[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(!st[j])
		{
			st[j]=true;
			if(match[j]==0 || find(match[j]))
			{
				match[j]=x;
				return true;
			}
		}
	}
	return false;
}

int main()
{
	cin>>n>>m;
	memset(h,-1,sizeof h);
	while(m--)
	{
		int u,v;
		cin>>u>>v;
		add(u,v);
	}
	int res=0;
	for(int i=1;i<=n;i++)
	{
		memset(st,false,sizeof st);
		if(find(i)) res++;
	}
	cout<<res<<endl;
	
	return 0;
}

🚩 运行结果:

G - Til the Cows Come Home

0x00 算法题目

0x01 算法思路

Dijkstra算法基础模板题

💬 模板演示:

cpp 复制代码
int dijkstra()
{
    memset(dist,0x3f,sizeof dist);

    dist[1]=0;

    for(int i=0;i<n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
        {
            if(!st[j] && (t==-1 || dist[t] > dist[j]))
                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];

}

0x02 代码实现

💬 代码演示:

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stdbool.h>

using namespace std;

const int N=1010,inf = 0x3f3f3f3f;

int n,m;
bool st[N];
int dist[N];
int g[N][N];

int dijkstra()
{
	memset(dist,inf,sizeof(dist));
	dist[1]= 0;
	for(int i=1;i <= n;i++)
	{
		int t=-1;
		for(int j=1;j<=n;j++)
			if(!st[j] && (t==-1 || dist[t] > dist[j]))
				t=j;
		
		st[t]=true;
		for(int j=1;j<=n;j++)
			dist[j]=min(dist[j],dist[t]+g[t][j]);
	}
	return dist[n];
}


int main()
{
	cin>>m>>n;
	memset(g,inf,sizeof g);
	
	for(int i=0;i<m;++i)
	{
		int a,b,c;
		cin>>a>>b>>c; 
		g[a][b]=g[b][a]=min(g[a][b],c);
	}
	cout<< dijkstra() <<endl;
	return 0;
}

🚩 运行结果:

H - 拓扑排序

0x00 算法题目

0x01 算法思路

拓扑排序算法基础模板题

💬 模板演示:

cpp 复制代码
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];
            if (-- d[j] == 0)
                q[ ++ tt] = j;
        }
    }
    return tt==n-1;
}

0x02 代码实现

💬 代码演示:

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>

using namespace std;

const int N=100010;

int n,m;
vector<int> v[N];
int size,d[N];
int ans[N];

void topsort()
{
	priority_queue<int,vector<int>,greater<int> > q;
	for(int i=1;i<=n;i++)
		if(!d[i]) q.push(i);
	
	while(!q.empty())
	{
		int t = q.top();
		q.pop();
		ans[size++] = t;
		for(auto it : v[t])
		{
			d[it]--;
			if(!d[it]) q.push(it);
		}
	}
}

int main()
{
	cin>>n>>m;
	
	for(int i=0;i<m;i++)
	{
		int a,b;
		cin>>a>>b;
		v[a].push_back(b);
		d[b]++;
	}
	topsort();
	
	for(int i=0 ; i<size ;i++)
		cout<< 'v' << ans[i] <<' ';
	
	return 0;
}

🚩 运行结果:


总结

这次训练很明显涉及到了最短路Dijkstra,spfa,图论二分图算法,以及topsort算法,这次考的比较基础,但是让我意识到了,算法必须熟练记忆模板是很重要的。

相关推荐
小字节,大梦想23 分钟前
【C++】二叉搜索树
数据结构·c++
吾名招财24 分钟前
yolov5-7.0模型DNN加载函数及参数详解(重要)
c++·人工智能·yolo·dnn
我是哈哈hh43 分钟前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
憧憬成为原神糕手1 小时前
c++_ 多态
开发语言·c++
郭二哈1 小时前
C++——模板进阶、继承
java·服务器·c++
Tisfy1 小时前
LeetCode 2187.完成旅途的最少时间:二分查找
算法·leetcode·二分查找·题解·二分
挥剑决浮云 -1 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
Mephisto.java1 小时前
【力扣 | SQL题 | 每日四题】力扣2082, 2084, 2072, 2112, 180
sql·算法·leetcode
robin_suli1 小时前
滑动窗口->dd爱框框
算法
丶Darling.1 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树