7-8路径判断
路径判断
给定一个有N个顶点和E条边的无向图,请判断给定的两个顶点之间是否有路径存在。 假设顶点从0到N−1编号。
输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。
随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。
最后一行给出两个顶点编号i,j(0≤i,j<N),i和j之间用空格分隔。
输出格式:
如果i和j之间存在路径,则输出"There is a path between i and j.",
否则输出"There is no path between i and j."。
输入样例1:
7 6
0 1
2 3
1 4
0 2
1 3
5 6
0 3
输出样例1:
There is a path between 0 and 3.
输入样例2:
7 6
0 1
2 3
1 4
0 2
1 3
5 6
0 6
输出样例2:
There is no path between 0 and 6.
代码基于并查集
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 110;
int p[N];
int n,m;
int x,y;
int find(int x)
{
if(p[x]!=x) p[x]=find(p[x]); //区间合并+路径压缩
return p[x];
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) p[i]=i; //初始化
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
if(find(a)!=find(b)) p[find(a)]=find(b);// 如果不在一个集合中加到一个集合中去
}
cin>>x>>y;
if(find(x)==find(y))
printf("There is a path between %d and %d.\n",x,y);
else
printf("There is no path between %d and %d.\n",x,y);
return 0;
}
代码基于floyd
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 110,INF=0x3f3f3f3f;
int p[N];
int n,m;
int x,y;
int g[N][N];
void floyd()
{
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g); //或把对角线初始化为0 结尾就少一个判断
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
g[a][b]=g[b][a]=1;
}
floyd();
cin>>x>>y;
if(x==y)
printf("There is a path between %d and %d.\n",x,y);
else if(g[x][y]==INF)
printf("There is no path between %d and %d.\n",x,y);
else
printf("There is a path between %d and %d.\n",x,y);
return 0;
}
代码基于spfa(可找负环)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N = 200,INF=0x3f3f3f3f;
int e[N],ne[N],w[N],h[N],idx;
int n,m;
int x,y;
int dist[N];
bool st[N];
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void spfa()
{
queue<int> q;
memset(dist , 0x3f, sizeof dist);
dist[x]=0;
st[x]=true;
q.push(x);
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])
{
st[j]=true;
q.push(j);
}
}
}
}
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=0;i<m;i++)
{
int a,b,c=1;
cin>>a>>b;
add(a,b,c);
add(b,a,c);
}
cin>>x>>y;
spfa();
if(dist[y]==INF)
printf("There is no path between %d and %d.\n",x,y);
else
printf("There is a path between %d and %d.\n",x,y);
return 0;
}
代码基于bellman_ford(用于有限条边求最短路,可找负环)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200,INF=0x3f3f3f3f;
int dist[N];
int last[N];
int n,m;
int x,y;
struct Edge
{
int a,b,w;
}d[N];
void bellman_ford()
{
memset(dist, 0x3f, sizeof dist);
dist[x]=0;
for(int i=0;i<2*m;i++) //最多不超过2*m条边 的最短路径
{
memcpy(last,dist,sizeof dist);//复制dist给last
for(int j=0;j<2*m;j++) //每次往外扩一条边
{
auto e=d[j];
dist[e.b]=min(dist[e.b],last[e.a]+e.w); //用上一次的dist去更新才能保证不超过边数的限制
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b,c=1;
cin>>a>>b;
d[i]={a,b,c};
d[m+i]={b,a,c};
}
cin>>x>>y;
bellman_ford();
if(dist[y]>INF/2) //因位可能存在负权边
printf("There is no path between %d and %d.\n",x,y);
else
printf("There is a path between %d and %d.\n",x,y);
}
代码基于dijkstra(邻接表)(不能处理负环)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 110;
typedef pair<int, int> PII;
int ne[N],e[N],w[N],h[N],idx;
int dist[N];
bool st[N];
int n,m;
int x,y;
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void dijkstra()
{
priority_queue<PII,vector<PII>,greater<PII>> heap;
memset(dist , 0x3f , sizeof dist);
dist[x]=0;
heap.push({0,x}); //起点
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});
}
}
}
}
int main()
{
cin>>n>>m;
memset(h , -1, sizeof h);
for(int i=0;i<m;i++)
{
int a,b,c=1;
cin>>a>>b;
add(a,b,c);
add(b,a,c);
}
cin>>x>>y;
dijkstra();
if(dist[y]==0x3f3f3f3f)
printf("There is no path between %d and %d.\n",x,y);
else
printf("There is a path between %d and %d.\n",x,y);
return 0;
}
代码基于dijkstra(邻接矩阵) (和prim求最小生成树思想差不多)prim模板(点进去滑倒最后)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510;
int g[N][N]; // a到b的距离
int dist[N]; //点到1的距离
bool st[N]; //找到最小距离的点,标记是否被搜过
int n,m;
int x,y;
void dijkstra()
{
memset(dist , 0x3f ,sizeof dist);
dist[x]=0; //把起点存入
for(int i=0;i<n-1;i++)
{
int t=-1;
for(int j=0;j<n;j++)
if(!st[j]&&(t==-1||dist[t]>dist[j]))
t=j; //距离最小没被搜过的点
//用点t更新其他点距离
for(int j=0;j<n;j++)
dist[j]=min(dist[j],g[t][j]+dist[t]); //1到j的距离与1到t+t到j的距离比较
st[t]=true;
}
}
int main()
{
cin>>n>>m;
memset(g , 0x3f , sizeof g);
for(int i=0;i<m;i++)
{
int a,b,c=1;
cin>>a>>b;
g[a][b]=g[b][a]=min(g[a][b],c);//无向图 min(g[a][b],c)去掉重边
}
cin>>x>>y;
dijkstra();
if(dist[y]>0x3f3f3f3f/2)
printf("There is no path between %d and %d.\n",x,y);
else
printf("There is a path between %d and %d.\n",x,y);
return 0;
}

浙公网安备 33010602011771号