1.朴素版Dijkstra
题目:A - Til the Cows Come Home
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int mp[1010][1010],dist[1010],vis[1010];
void Dij()
{
for(int i=1;i<=n;i++)dist[i]=mp[n][i];
vis[n]=1;
for(int i=1;i<=n;i++)
{
int f=-1;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&(f==-1||dist[f]>dist[j]))f=j;
}
vis[f]=1;
for(int j=1;j<=n;j++)
{
if(!vis[j])dist[j]=min(dist[j],dist[f]+mp[f][j]);
}
}
printf("%d\n",dist[1]);
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)mp[i][j]=0;
else mp[i][j]=INF;
}
}
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(mp[x][y]>z)mp[x][y]=mp[y][x]=z;
}
memset(vis,0,sizeof(vis));
Dij();
}
return 0;
}
2.堆优化Dijkstra
题目:
给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为非负值。
请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 −1。
输入格式
第一行包含整数 n 和 m。
接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。
输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。
如果路径不存在,则输出 −1。
数据范围
1≤n,m≤1.5×105,
图中涉及边长均不小于 0,且不超过 10000。
输入样例:
3 3
1 2 2
2 3 1
1 3 4
输出样例:
3
const int N=150010;
int n,m;
int h[N],w[N],e[N],ne[N],idx;
typedef pair<int,int>PII;
int dist[N],vis[N];
void add(int a,int b,int c)
{
e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
void Dij()
{
priority_queue<PII,vector<PII>,greater<PII> >heap;
dist[1]=0;
heap.push({0,1});
while(!heap.empty())
{
PII t=heap.top();heap.pop();
int ver=t.second,dis=t.first;
if(vis[ver])continue;
vis[ver]=1;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dis+w[i])
{
dist[j]=dis+w[i];
heap.push({dist[j],j});
}
}
}
if(dist[n]==INF)printf("-1\n");
else printf("%d\n",dist[n]);
}
int main()
{
memset(h,-1,sizeof(h));
memset(vis,0,sizeof(vis));
memset(dist,INF,sizeof(dist));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
Dij();
return 0;
}
3.Bellman-Ford算法
给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。
请你求出从 1 号点到 n 号点的最多经过 k 条边的最短距离,如果无法从 1 号点走到 n 号点,输出 impossible。
注意:图中可能 存在负权回路 。
输入格式
第一行包含三个整数 n,m,k。
接下来 m 行,每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。
输出格式
输出一个整数,表示从 1 号点到 n 号点的最多经过 k 条边的最短距离。
如果不存在满足条件的路径,则输出 impossible。
数据范围
1≤n,k≤500,
1≤m≤10000,
任意边长的绝对值不超过 10000。
输入样例:
3 3 1
1 2 1
2 3 1
1 3 3
输出样例:
3
int n,m,k;
struct edges
{
int a,b,w;
}edge[10010];
int dist[510],backup[510];
void bellman()
{
memset(dist,INF,sizeof(dist));
dist[1]=0;
for(int i=0;i<k;i++)
{
memcpy(backup,dist,sizeof(dist));
for(int j=1;j<=m;j++)
{
int a=edge[j].a,b=edge[j].b,w=edge[j].w;
dist[b]=min(dist[b],w+backup[a]);
}
}
if(dist[n]>INF/2)printf("impossible\n");
else printf("%d\n",dist[n]);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].w);
}
bellman();
return 0;
}
4.SPFA算法
给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。
请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 impossible。
数据保证不存在负权回路。
输入格式
第一行包含整数 n 和 m。
接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。
输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。
如果路径不存在,则输出 impossible。
数据范围
1≤n,m≤105,
图中涉及边长绝对值均不超过 10000。
输入样例:
3 3
1 2 5
2 3 -3
1 3 4
输出样例:
2
const int N=100010;
int h[N],w[N],e[N],ne[N],idx;
int dist[N],vis[N];
int n,m;
void add(int a,int b,int c)
{
e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
void SPFA()
{
memset(dist,INF,sizeof(dist));
memset(vis,0,sizeof(vis));
queue<int>q;
dist[1]=0;
q.push(1);
vis[1]=1;
while(!q.empty())
{
int t=q.front();
q.pop();
vis[t]=0;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>w[i]+dist[t])
{
dist[j]=w[i]+dist[t];
if(!vis[j])
{
q.push(j);
vis[j]=1;
}
}
}
}
if(dist[n]==INF)printf("impossible\n");
else printf("%d\n",dist[n]);
}
int main()
{
memset(h,-1,sizeof(h));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
SPFA();
return 0;
}
5.Floyd算法
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
Sample Output
2
-1
int mp[210][210];
int n,m;
int s,t;
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j)mp[i][j]=0;
else mp[i][j]=INF;
}
}
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(mp[a][b]>c)mp[a][b]=mp[b][a]=c;
}
scanf("%d%d",&s,&t);
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(mp[i][j]>mp[i][k]+mp[k][j])mp[i][j]=mp[i][k]+mp[k][j];
}
}
}
if(mp[s][t]==INF)printf("-1\n");
else printf("%d\n",mp[s][t]);
}
return 0;
}
6.bellmon判断是否存在正环
题目:E - Currency Exchange
int n,m,s;
double v;
struct cur
{
int a,b;
double r,c;
}cc[210];
double dist[110];
void bellmon()
{
memset(dist,0,sizeof(dist));
dist[s]=v;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=2*m;j++)
{
if((dist[cc[j].a]-cc[j].c)*cc[j].r>dist[cc[j].b])
dist[cc[j].b]=(dist[cc[j].a]-cc[j].c)*cc[j].r;
}
}
int flag=0;
for(int j=1;j<=2*m;j++)
{
if((dist[cc[j].a]-cc[j].c)*cc[j].r>dist[cc[j].b])
{
flag=1;
break;
}
}
if(flag==1)printf("YES\n");
else printf("NO\n");
}
int main()
{
while(~scanf("%d%d%d%lf",&n,&m,&s,&v))
{
for(int i=1;i<=m;i++)
{
int a,b;
double rab,cab,rba,cba;
scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);
cc[i].a=a;cc[i].b=b;cc[i].r=rab;cc[i].c=cab;
cc[i+m].a=b;cc[i+m].b=a;cc[i+m].r=rba;cc[i+m].c=cba;
}
bellmon();
}
return 0;
}
7…bellmon判断是否存在负环
F - Wormholes
int t,n,m,w;
struct path
{
int a,b,c;
}pp[5500];
int dist[510];
void bellmon()
{
memset(dist,INF,sizeof(dist));
dist[1]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m*2+w;j++)
{
if(dist[pp[j].b]>dist[pp[j].a]+pp[j].c&&dist[pp[j].a]!=INF)
dist[pp[j].b]=dist[pp[j].a]+pp[j].c;
}
}
int flag=0;
for(int j=1;j<=m*2+w;j++)
{
if(dist[pp[j].b]>dist[pp[j].a]+pp[j].c)
{
flag=1;
break;
}
}
if(flag==1)printf("YES\n");
else printf("NO\n");
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&w);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&pp[i].a,&pp[i].b,&pp[i].c);
pp[i+m].a=pp[i].b;pp[i+m].b=pp[i].a;pp[i+m].c=pp[i].c;
}
for(int i=m*2+1;i<=m*2+w;i++)
{
scanf("%d%d%d",&pp[i].a,&pp[i].b,&pp[i].c);
pp[i].c=-pp[i].c;
}
bellmon();
}
return 0;
}