dijkstra算法
算法笔记版
const int inf = 1e9;
const int maxn = 1005;
int g[maxn][maxn];
int d[maxn];
bool vi[maxn];
vector<int> pre[maxn];
int n;
void dj(int s) {
fill(d, d + maxn, inf);
d[s] = 0;
for (int i = 0; i < n; i++) {
int u = -1, minn = inf;
for (int j = 0; j < n; j++) {
if (vi[j] == false && d[j] < minn) {
u = j;
minn = d[j];
}
}
if (u == -1)return;
vi[u] = true;
for (int v = 0; v < n; v++) {
if (!vi[v] && g[u][v] != inf) {
if (d[u] + g[u][v] < d[v]) {
d[v] = d[u] + g[u][v];
pre[v].clear();
pre[v].push_back(u);
}
else if (d[u] + g[u][v] == d[v]) {
pre[v].push_back(u);
}
}
}
}
}
y总版
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=510;
int g[N][N];
bool vi[N];
int d[N];
int n,m;
void dj(){
memset(d, 0x3f,sizeof d);
d[1]=0;
for(int i=1;i<=n;i++){
int u=-1,minn=inf;
for(int j=1;j<=n;j++ ){
if(!vi[j] && (u==-1 || d[j]<d[u])){
minn=d[j];
u=j;
}
}
if(u==-1)return ;
vi[u]=true;
for (int j = 1; j <= n; ++j) {
d[j] = min(d[j], d[u] + g[u][j]);
}
}
}
int main(){
cin>>n>>m;
memset(g, 0x3f, sizeof g);
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
g[a][b]=min(g[a][b],c);
}
dj();
if(d[n]==inf)cout<<"-1";
else cout<<d[n];
return 0;
}
堆优化dijkstra
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e6;
int n,m;
int h[N],w[N],e[N],ne[N],idx;
int d[N];
bool vi[N];
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++;
}
void dj(){
memset(d,0x3f, sizeof d);
d[1]=0;
priority_queue<PII,vector<PII>,greater<PII> > q;
q.push({0,1});
while(q.size()){
auto t=q.top();
q.pop();
int u=t.second;
if(vi[u])continue;
vi[u]=true;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(d[v]>d[u]+w[i]){
d[v]=d[u]+w[i];
q.push({d[v],v});
}
}
}
}
int main(){
memset(h, -1, sizeof h);
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
dj();
if(d[n]==inf) cout<<"-1";
else cout<<d[n]<<endl;
return 0;
}
bellman-ford算法
int n, m; // n表示点数,m表示边数
int dist[N]; // dist[x]存储1到x的最短路距离
struct Edge // 边,a表示出点,b表示入点,w表示边的权重
{
int a, b, w;
}edges[M];
// 求1到n的最短路距离,如果无法从1走到n,则返回-1。
int bellman_ford()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
// 如果第n次迭代仍然会松弛三角不等式,就说明存在一条长度是n+1的最短路径,由抽屉原理,路径中至少存在两个相同的点,说明图中存在负权回路。
for (int i = 0; i < n; i ++ )
{
for (int j = 0; j < m; j ++ )
{
int a = edges[j].a, b = edges[j].b, w = edges[j].w;
if (dist[b] > dist[a] + w)
dist[b] = dist[a] + w;
}
}
if (dist[n] > 0x3f3f3f3f / 2) return -1;
return dist[n];
}
spfa算法(求最短路,不能有负环)
链表前向星版
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int h[N],e[N],w[N],ne[N],idx;
bool st[N];
int d[N];
void add(int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
void spfa(){
memset(d, 0x3f, sizeof d);
d[1]=0;
queue<int> q;
q.push(1);
st[1]=true;
while(q.size()){
auto u=q.front();
q.pop();
st[u]=false;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(d[v]>d[u]+w[i]){
d[v]=d[u]+w[i];
if(!st[v]){
q.push(v);
st[v]=true;
}
}
}
}
}
int main(){
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
spfa();
if(d[n]==inf)cout<<"impossible";
else cout<<d[n];
return 0;
}
stl版
struct node{
int v;
int dis;
};
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int d[N];
vector<node> g[N];
bool st[N];
//返回点s到点ed的距离,若res==inf,则不可达
int spfa(int s,int ed){
memset(d,0x3f,sizeof d);
d[s]=0;
queue<int> q;
q.push(s);
st[s]=true;
while(q.size()){
int t=q.front();
q.pop();
st[t]=false;
for(int i=0;i<g[t].size();i++){
int v=g[t][i].v;
int dis=g[t][i].dis;
if(d[v]>d[t]+dis){
d[v]=d[t]+dis;
if(!st[v]){
q.push(v);
st[v]=true;
}
}
}
}
return d[ed];
}
spfa(求是否有负环)
链表前向星版
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int h[N],e[N],w[N],ne[N],idx;
bool st[N];
int d[N],cnt[N];
void add(int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
bool spfa(){
queue<int> q;
for(int i=1;i<=n;i++){
q.push(i);
st[i]=true;
}
while(q.size()){
auto u=q.front();
q.pop();
st[u]=false;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(d[v]>d[u]+w[i]){
d[v]=d[u]+w[i];
cnt[v]=cnt[u]+1;
if(cnt[v]>=n)return true;
if(!st[v]){
q.push(v);
st[v]=true;
}
}
}
}
return false;
}
int main(){
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
spfa();
if(spfa())cout<<"Yes";
else cout<<"No";
return 0;
}
stl版
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
struct node{
int y;
int w;
};
const int inf=0x3f3f3f3f;
const int N=2010;
int n,m;
vector<node>g[N];
int d[N],cnt[N];
bool st[N];
bool spfa(){
queue<int > q;
for(int i=1;i<=n;i++){
st[i]=true;
q.push(i);
}
while(q.size()){
int t=q.front();
q.pop();
st[t]=false;
for(int i=0;i<g[t].size();i++){
int v=g[t][i].y;
int dis=g[t][i].w;
if(d[v]>d[t]+dis){
cnt[v]=cnt[t]+1;
if(cnt[v]>=n)return true;//有负环
d[v]=d[t]+dis;
if(!st[v]){
st[v]=true;
q.push(v);
}
}
}
}
return false;
}
int main(){
cin>>n>>m;
for(int i=0;i<m;i++){
int a,b,c;
cin>>a>>b>>c;
g[a].push_back({b,c});
}
bool res=spfa();
if(res==true) cout<<"Yes";
else cout<<"No";
return 0;
}
拓扑排序
const int maxn=1e5+10;
int n,m;
vector<int> g[maxn];
int d[maxn];
vector<int> res;//存储拓扑排序序列
bool topsort(){
queue<int> q;
int num=0;
for(int i=1;i<=n;i++){
if(d[i]==0) q.push(i);
}
while(!q.empty()){
int u=q.front();
q.pop();
num++;
res.push_back(u);
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(--d[v]==0) q.push(v);
}
}
if(num==n) return true;
else return false;
}