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;
}
posted @ 2021-11-06 16:36  三枪一个麻辣烫  阅读(36)  评论(0)    收藏  举报  来源