SDUT--OJ《数据结构与算法》实践能力专题训练6 图论

2023-11-19

A - 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历

Description

给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列。(同一个结点的同层邻接点,节点编号小的优先遍历)

Input

输入第一行为整数n(0< n <100),表示数据的组数。
对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,0< t<k),表示有m条边,k个顶点,t为遍历的起始顶点。
下面的m行,每行是空格隔开的两个整数u,v,表示一条连接u,v顶点的无向边。

Output

输出有n行,对应n组输出,每行为用空格隔开的k个整数,对应一组数据,表示BFS的遍历结果。

Sample

Input 

1
6 7 0
0 3
0 4
1 4
1 5
2 3
2 4
3 5

Output 

0 3 4 2 5 1

Hint

以邻接矩阵作为存储结构。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int  N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
void bfs(int s)
{
   int in,out;
   in=out=0;
   ch[in++]=s;
   dis[s]=1;
   while(in>out)
   {
      int u=ch[out];
      for(int i=0;i<n;i++)
      {
         if(dis[i]==0&&vis[u][i]==1)
         {
            ch[in++]=i;
            dis[i]=1;
         }
      }
      out++;
   }
   for(int i=0;i<in;i++)
       {
          if(i==in-1)
          {
             printf("%d\n",ch[i]);
          }
          else
          {
             printf("%d ",ch[i]);
          }
       }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
       scanf("%d %d %d",&n,&m,&s);
       memset(dis,0,sizeof(dis));
       memset(vis,0,sizeof(vis));
       memset(ch,0,sizeof(ch));
       for(int i=0;i<m;i++)
       {
           int u,v;
           scanf("%d %d",&u,&v);
           vis[u][v]=vis[v][u]=1;
       }
       bfs(s);
    }
    return 0;
}

 

B - 数据结构实验之图论二:图的深度遍历

Description

请定一个无向图,顶点编号从0到n-1,用深度优先搜索(DFS),遍历并输出。遍历时,先遍历节点编号小的。

Input

输入第一行为整数n(0 < n < 100),表示数据的组数。 对于每组数据,第一行是两个整数k,m(0 < k < 100,0 < m < k*k),表示有m条边,k个顶点。 下面的m行,每行是空格隔开的两个整数u,v,表示一条连接u,v顶点的无向边。

Output

输出有n行,对应n组输出,每行为用空格隔开的k个整数,对应一组数据,表示DFS的遍历结果。

Sample

Input 

1
4 4
0 1
0 2
0 3
2 3

Output 

0 1 2 3

 

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int  N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
void dfs(int s)
{
   dis[s]=1;
   ch[top++]=s;
   for(int i=0;i<n;i++)
   {
      if(dis[i]==0&&vis[s][i]==1)
      {
         dfs(i);
      }
   }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
       scanf("%d %d",&n,&m);
       memset(dis,0,sizeof(dis));
       memset(vis,0,sizeof(vis));
       memset(ch,0,sizeof(ch));
       for(int i=0;i<m;i++)
       {
           int u,v;
           scanf("%d %d",&u,&v);
           vis[u][v]=vis[v][u]=1;
       }
       top=0;
       dfs(0);
       for(int i=0;i<top;i++)
       {
          if(i==top-1)
          {
             printf("%d\n",ch[i]);
          }
          else
          {
             printf("%d ",ch[i]);
          }
       }
    }
    return 0;
}

 

C - 数据结构实验之图论三:判断可达性

Description

 在古老的魔兽传说中,有两个军团,一个叫天灾,一个叫近卫。在他们所在的地域,有n个隘口,编号为1..n,某些隘口之间是有通道连接的。其中近卫军团在1号隘口,天灾军团在n号隘口。某一天,天灾军团的领袖巫妖王决定派兵攻打近卫军团,天灾军团的部队如此庞大,甚至可以填江过河。但是巫妖王不想付出不必要的代价,他想知道在不修建任何通道的前提下,部队是否可以通过隘口及其相关通道到达近卫军团展开攻击。由于n的值比较大(n<=1000),于是巫妖王找到了擅长编程的你 =_=,请你帮他解决这个问题,否则就把你吃掉变成他的魔法。为了拯救自己,赶紧想办法吧。

 

Input

 输入包含多组,每组格式如下。

第一行包含两个整数n,m(分别代表n个隘口,这些隘口之间有m个通道)。

下面m行每行包含两个整数a,b;表示从a出发有一条通道到达b隘口(注意:通道是单向的)。

Output

 如果天灾军团可以不修建任何通道就到达1号隘口,那么输出YES,否则输出NO。

 

Sample

Input 

2 1
1 2
2 1
2 1

Output 

NO
YES

 

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int  N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
void dfs(int s)
{
   dis[s]=1;
   for(int i=0;i<n;i++)
   {
      if(dis[i]==0&&vis[s][i]==1)
      {
         dfs(i);
      }
   }
}
int main()
{
    int t;

    while(~scanf("%d %d",&n,&m))
    {
       memset(dis,0,sizeof(dis));
       memset(vis,0,sizeof(vis));
       memset(ch,0,sizeof(ch));
       for(int i=0;i<m;i++)
       {
           int u,v;
           scanf("%d %d",&u,&v);
           vis[u][v]=1;
       }
       top=0;
       dfs(n);
       if(dis[1]==1)
       {
          printf("YES\n");
       }
       else
       {
          printf("NO\n");
       }
    }
    return 0;
}

D - 数据结构实验之图论四:迷宫探索

Description

有一个地下迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关;请问如何从某个起点开始在迷宫中点亮所有的灯并回到起点?

Input

连续T组数据输入,每组数据第一行给出三个正整数,分别表示地下迷宫的结点数N(1 < N <= 1000)、边数M(M <= 3000)和起始结点编号S,随后M行对应M条边,每行给出一对正整数,表示一条边相关联的两个顶点的编号。

 

Output

若可以点亮所有结点的灯,则输出从S开始并以S结束的序列,序列中相邻的顶点一定有边,否则只输出部分点亮的灯的结点序列,最后输出0,表示此迷宫不是连通图。
访问顶点时约定以编号小的结点优先的次序访问,点亮所有可以点亮的灯后,以原路返回的方式回到起点。

Sample

Input 

1
6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5

Output 

1 2 3 4 5 6 5 4 3 2 1

Hint

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int  N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
void dfs(int s)
{
   dis[s]=1;
   ch[top++]=s;
   for(int i=1;i<=n;i++)
   {
      if(dis[i]==0&&vis[s][i]==1)
      {
         dis[i]=1;
         dfs(i);
         ch[top++]=s;
      }
   }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
       scanf("%d %d %d",&n,&m,&s);
       memset(dis,0,sizeof(dis));
       memset(vis,0,sizeof(vis));
       memset(ch,0,sizeof(ch));
       for(int i=0;i<m;i++)
       {
           int u,v;
           scanf("%d %d",&u,&v);
           vis[u][v]=vis[v][u]=1;
       }
       top=0;
       dfs(s);
       for(int i=0;i<top;i++)
       {
          if(i==top-1)
          {
             printf("%d",ch[i]);
          }
          else
          {
             printf("%d ",ch[i]);
          }
       }
       if(top!=2*n-1)
       {
          printf(" 0\n");
       }
       else
       {
          printf("\n");
       }
    }
    return 0;
}

E - 数据结构实验之图论五:从起始点到目标点的最短步数(BFS)

Description

 在古老的魔兽传说中,有两个军团,一个叫天灾,一个叫近卫。在他们所在的地域,有n个隘口,编号为1..n,某些隘口之间是有通道连接的。其中近卫军团在1号隘口,天灾军团在n号隘口。某一天,天灾军团的领袖巫妖王决定派兵攻打近卫军团,天灾军团的部队如此庞大,甚至可以填江过河。但是巫妖王不想付出不必要的代价,他想知道在不修建任何通道的前提下,部队是否可以通过隘口及其相关通道到达近卫军团展开攻击;如果可以的话,最少需要经过多少通道。由于n的值比较大(n<=1000),于是巫妖王找到了擅长编程的你 =_=,请你帮他解决这个问题,否则就把你吃掉变成他的魔法。为了拯救自己,赶紧想办法吧。

 

Input

 输入包含多组,每组格式如下。

第一行包含两个整数n,m(分别代表n个隘口,这些隘口之间有m个通道)。

下面m行每行包含两个整数a,b;表示从a出发有一条通道到达b隘口(注意:通道是单向的)。

 

Output

 如果天灾军团可以不修建任何通道就到达1号隘口,那么输出最少经过多少通道,否则输出NO。

 

Sample

Input 

2 1
1 2
2 1
2 1

Output 

NO
1
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int  N=1010;
int dis[N];
int vis[N][N];
int n,m,s;
int ch[N];
int top=0;
struct node
{
    int data,step;
} e[N];
void bfs(int s)
{
    int in,out;
    in=out=0;
    e[in].data=s;
    e[in].step=0;
    in++;
    dis[s]=1;
    while(in>out)
    {
        int u=e[out].data;
        if(u==1)
        {
            break;
        }
        for(int i=1; i<=n; i++)
        {
            if(dis[i]==0&&vis[u][i]==1)
            {
                dis[i]=1;
                e[in].data=i;
                e[in].step=e[out].step+1;
                in++;
            }
        }
        out++;
    }
    if(in==out)
    {
        printf("NO\n");
    }
    else
    {
        printf("%d\n",e[out].step);
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        memset(dis,0,sizeof(dis));
        memset(vis,0,sizeof(vis));
        for(int i=0; i<m; i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            vis[u][v]=1;
        }
        bfs(n);
    }
    return 0;
}

 

F - 数据结构实验之图论六:村村通公路

Description

当前农村公路建设正如火如荼的展开,某乡镇政府决定实现村村通公路,工程师现有各个村落之间的原始道路统计数据表,表中列出了各村之间可以建设公路的若干条道路的成本,你的任务是根据给出的数据表,求使得每个村都有公路连通所需要的最低成本。

Input

连续多组数据输入,每组数据包括村落数目N(N <= 1000)和可供选择的道路数目M(M <= 3000),随后M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个村庄的编号和修建该道路的预算成本,村庄从1~N编号。 

Output

输出使每个村庄都有公路连通所需要的最低成本,如果输入数据不能使所有村庄畅通,则输出-1,表示有些村庄之间没有路连通。 

Sample

Input 

5 8
1 2 12
1 3 9
1 4 11
1 5 3
2 3 6
2 4 9
3 4 4
4 5 6

Output 

19

Hint

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int  N=101010;
struct node
{
    int u,v,w;
} e[N];
int f[N];
int m,n;
bool cmp(node x,node y)
{
    return x.w<y.w;
}
void init(int n)
{
    for(int i=0; i<=n; i++)
    {
        f[i]=i;
    }
}
int find1(int x)
{
    if(x!=f[x])
    {
        return f[x]=find1(f[x]);
    }
    else
    {
        return x;
    }
}
bool join(int x,int y)
{
    int fx=find1(x);
    int fy=find1(y);
    if(fx!=fy)
    {
        f[fx]=fy;
        return false;
    }
    else
    {
        return true;
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        init(n);
        for(int i=0; i<m; i++)
        {
            cin>>e[i].u>>e[i].v>>e[i].w;
        }
        sort(e,e+m,cmp);
        int ans=0;
        int cnt=0;
        for(int i=0; i<m; i++)
        {
            if(!join(e[i].u,e[i].v))
            {
                ans+=e[i].w;
                cnt++;
            }
        }
        if(cnt==n-1)
        {
        printf("%d\n",ans);
        }
        else
        {
          printf("-1\n");
        }
    }
    return 0;
}

G - 数据结构实验之图论七:驴友计划

Description

做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。

Input

连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。 

Output

在同一行中输出路径长度和收费总额,数据间用空格间隔。 

Sample

Input 

1
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

Output 

3 40

Hint

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int  N=1010;
int dis[N];
int vis[N][N];
int cis[N][N];
int n,m,s,d;
int ch[N];
int top=0;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
       scanf("%d %d %d %d",&n,&m,&s,&d);
       for(int i=0;i<n;i++)
       {
          for(int j=0;j<n;j++)
          {
             vis[i][j]=cis[i][j]=inf;
          }
       }
       for(int i=0;i<m;i++)
       {
           int u,v,w,cost;
           scanf("%d %d %d %d",&u,&v,&w,&cost);
           vis[u][v]=vis[v][u]=min(w,vis[u][v]);
           cis[u][v]=cis[v][u]=min(cost,cis[u][v]);
       }
       for(int k=0;k<n;k++)
       {
          for(int i=0;i<n;i++)
          {
             for(int j=0;j<n;j++)
             {
                if(vis[i][j]>vis[i][k]+vis[k][j])
                {
                   vis[i][j]=vis[i][k]+vis[k][j];
                   cis[i][j]=cis[i][k]+cis[k][j];
                }
                else if(vis[i][j]==vis[i][k]+vis[k][j]&&cis[i][j]>cis[i][k]+cis[k][j])
                {
                   cis[i][j]=cis[i][k]+cis[k][j];
                }
             }
          }
       }
       printf("%d %d\n",vis[s][d],cis[s][d]);
    }
    return 0;
}

H - 数据结构实验之图论八:欧拉回路

Description

在哥尼斯堡的一个公园里,有七座桥将普雷格尔河中两个岛及岛与河岸连接起来。



能否走过这样的七座桥,并且每桥只走一次?瑞士数学家欧拉最终解决了这个问题并由此创立了拓扑学。欧拉通过对七桥问题的研究,不仅圆满地回答了哥尼斯堡七桥问题,并证明了更为广泛的有关一笔画的三条结论,人们通常称之为欧拉定理。对于一个连通图,通常把从某结点出发一笔画成所经过的路线叫做欧拉路。人们又通常把一笔画成回到出发点的欧拉路叫做欧拉回路。具有欧拉回路的图叫做欧拉图。

你的任务是:对于给定的一组无向图数据,判断其是否成其为欧拉图?

Input

连续T组数据输入,每组数据第一行给出两个正整数,分别表示结点数目N(1 < N <= 1000)和边数M;随后M行对应M条边,每行给出两个正整数,分别表示该边连通的两个结点的编号,结点从1~N编号。 

Output

若为欧拉图输出1,否则输出0。

Sample

Input 

1
6 10
1 2
2 3
3 1
4 5
5 6
6 4
1 4
1 6
3 4
3 6

Output 

1

Hint

如果无向图连通并且所有结点的度都是偶数,则存在欧拉回路,否则不存在。 

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int dis[N];
int vis[N][N];
int m,n,s;
int ch[N];
int dp[N];
int top;
void dfs(int s)
{
    dis[s]=1;
    top++;
    for(int i=1;i<=n;i++)
    {
       if(!dis[i]&&vis[s][i]==1)
       {
          dis[i]=1;
          dfs(i);
       }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        memset(vis,0,sizeof(vis));
        memset(dis,0,sizeof(dis));
        memset(dp,0,sizeof(dp));
        for(int i=0;i<m;i++)
        {
           int u,v;
           scanf("%d %d",&u,&v);
           vis[u][v]=vis[v][u]=1;
           dp[u]++;
           dp[v]++;
        }
        top=0;
        dfs(1);
        int flag=0;
        for(int i=1;i<=n;i++)
        {
           if(dp[i]%2)
           {
              flag=1;
              break;
           }
        }
        if(flag==0&&top==n)
        {
           printf("1\n");
        }
        else
        {
           printf("0\n");
        }
    }
    return 0;
}

 

I - 数据结构实验之图论九:最小生成树

Description

 有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的。现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市。

 

Input

 输入包含多组数据,格式如下。

第一行包括两个整数n m,代表城市个数和可以修建的公路个数。(n <= 100, m <=10000)

剩下m行每行3个非负整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c(城市编号从1到n)。

 

Output

 每组输出占一行,仅输出最小花费。

Sample

Input 

3 2
1 2 1
1 3 1
1 0

Output 

2
0
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int  N=101010;
struct node
{
    int u,v,w;
} e[N];
int f[N];
int m,n;
bool cmp(node x,node y)
{
    return x.w<y.w;
}
void init(int n)
{
    for(int i=0; i<=n; i++)
    {
        f[i]=i;
    }
}
int find1(int x)
{
    if(x!=f[x])
    {
        return f[x]=find1(f[x]);
    }
    else
    {
        return x;
    }
}
bool join(int x,int y)
{
    int fx=find1(x);
    int fy=find1(y);
    if(fx!=fy)
    {
        f[fx]=fy;
        return false;
    }
    else
    {
        return true;
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        init(n);
        for(int i=0; i<m; i++)
        {
            cin>>e[i].u>>e[i].v>>e[i].w;
        }
        sort(e,e+m,cmp);
        int ans=0;
        int cnt=0;
        for(int i=0; i<m; i++)
        {
            if(!join(e[i].u,e[i].v))
            {
                ans+=e[i].w;
                cnt++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

J - 数据结构实验之图论十:判断给定图是否存在合法拓扑序列

Description

 给定一个有向图,判断该有向图是否存在一个合法的拓扑序列。

Input

 输入包含多组,每组格式如下。

第一行包含两个整数n,m,分别代表该有向图的顶点数和边数。(n<=10)

后面m行每行两个整数a b,表示从a到b有一条有向边。

 

Output

 若给定有向图存在合法拓扑序列,则输出YES;否则输出NO。

 

Sample

Input 

1 0
2 2
1 2
2 1

Output 

YES
NO

 

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1010;
int G[N][N];//图;
int dis[N];//入度;
int n;
queue<int>q;
void Tsort()
{
    for(int i=1; i<=n; i++)
    {
        if(!dis[i])//把入度为零的全部加入到队列中;
        {
            q.push(i);
        }
    }
    int cnt=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        cnt++;
        for(int i=1; i<=n; i++)
        {
            if(G[u][i]==1)
            {
            int v=i;//v是要服从于u的事件。
            if(dis[v])//如果v的入度不为零
                dis[v]--;
            if(dis[v]==0)//如果v的入度为零;
                q.push(v);//加入队列中;
            }
        }
    }
    if(cnt==n)
        printf("YES\n");
    else
        printf("NO\n");
}
int main()
{
    int m;
    while(~scanf("%d %d",&n,&m))
    {
        int a,b;
        memset(dis,0,sizeof(dis));
        memset(G,0,sizeof(G));
        for(int i=0; i<m; i++)
        {
            scanf("%d %d",&a,&b);
            G[b][a]=1;;
            dis[a]++;
        }
        Tsort();
    }
    return 0;
}

K - 老鼠走迷宫

Description

现在一只老鼠被困在了迷宫里!你需要判断老鼠能否走出迷宫。

老鼠只能向上下左右四个方向移动。我们认为只要老鼠走到了迷宫的边界即算走出迷宫。

Input

第一行输入两个整数 nnn, mmm (1⩽n,m⩽100)(1 \leqslant n, m \leqslant 100)(1⩽n,m⩽100) 表示迷宫地图的尺寸。

接下来输入 nnn 行,每行 mmm 个字符,表示迷宫地图。其中 M 表示老鼠的位置,* 代表墙壁,. 代表空地。

Output

如果老鼠可以走出迷宫,则输出一行 Yes,否则输出一行 No

Sample

Input 

4 4
*.**
*..*
*.M*
****

Output 

Yes

Hint

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int dis[3010][3010];
int vis[3030][3030];
int v[1010];
int m,n;
int inf=0x3f3f3f3f;
int flag=0;
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
void dfs(int x,int y)
{
    dis[x][y]=1;
    if(x==0||y==0||x==n-1||y==m-1)
    {
       flag=1;
       return;
    }
     for(int i=0;i<4;i++)
     {
        int xx=x+dx[i];
        int yy=y+dy[i];
        if(vis[xx][yy]==1&&dis[xx][yy]==0&&xx>=0&&xx<n&&yy>=0&&yy<m)
        {
          dfs(xx,yy);
        }
     }

}
int main()
{
    scanf("%d %d",&n,&m);
    int i,j;
    char s;
    int x,y;
    for(i=0;i<n;i++)
    {
        getchar();
        for(j=0;j<m;j++)
        {
            scanf("%c",&s);
            if(s=='*')
            {
                vis[i][j]=0;
            }
            else if(s=='.')
            {
                vis[i][j]=1;
            }
            else
            {
                vis[i][j]=1;
                x=i;
                y=j;
            }
        }
    }
    flag=0;
    memset(dis,0,sizeof(dis));
    dfs(x,y);
    if(flag==0)
    {
        printf("No\n");
    }
    else
    {
        printf("Yes\n");
    }
    return 0;
}

L - 病毒扩散

Description

2019-ncov的突然出现扰乱了人们的日常生活,它具有极强的传染性,可以快速的在人群中扩散,现在研究人员正在模拟其在人群中的扩散情况.

在一个n*m矩阵所示的人群中,*为普通人,#为佩戴口罩的人,@为病毒携带者,已知每秒每位病毒携带者会将病毒传染给相邻八个方向的未戴口罩的普通人。请问 x 秒后会有多少名传染者(初始为第0秒)?

Input

第一行输入空格分隔的三个数n,m,x代表n行,m列的空间,x秒(n,m<=1000)。

接下来n行每行m人如上述所示。

Output

一个数字,代表最终被传染的人数。

Sample

Input 

4 4 2
****
*@**
**##
**#*

Output 

12
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int dis[3010][3010];
int vis[3030][3030];
int m,n;
int inf=0x3f3f3f3f;
int flag=0;
int dx[]= {-1,1,0,0,1,1,-1,-1};
int dy[]= {0,0,-1,1,1,-1,1,-1};
int in,out;
struct node
{
   int x,y;
}v[1001000];
void bfs(int x,int y)
{
    for(int i=0;i<8;i++)
    {
       int xx=x+dx[i];
       int yy=y+dy[i];
       if(vis[xx][yy]==1&&dis[xx][yy]==0&&xx>=0&&xx<n&&yy>=0&&yy<m)
       {
          dis[xx][yy]=1;
          v[in].x=xx;
          v[in].y=yy;
          in++;
       }
    }
}
int main()
{
    int k;
    scanf("%d %d %d",&n,&m,&k);
    int i,j;
    char s;
    int x,y;
    in=out=0;
    memset(dis,0,sizeof(dis));
    for(i=0;i<n;i++)
    {
        getchar();
        for(j=0;j<m;j++)
        {
            scanf("%c",&s);
            if(s=='#')
            {
                vis[i][j]=0;
            }
            else if(s=='*')
            {
                vis[i][j]=1;
            }
            else
            {
                vis[i][j]=1;
                dis[i][j]=1;
                v[in].x=i;
                v[in].y=j;
                in++;
            }
        }
    }
    for(i=0;i<k;i++)
    {
       int DD=in;
       while(out<DD)
       {
          bfs(v[out].x,v[out].y);
          out++;
       }
    }
    printf("%d\n",in);
    return 0;
}

 

M - 魔戒

Description

蓝色空间号和万有引力号进入了四维水洼,发现了四维物体--魔戒。

这里我们把飞船和魔戒都抽象为四维空间中的一个点,分别标为 "S" 和 "E"。空间中可能存在障碍物,标为 "#",其他为可以通过的位置。

现在他们想要尽快到达魔戒进行探索,你能帮他们算出最小时间是最少吗?我们认为飞船每秒只能沿某个坐标轴方向移动一个单位,且不能越出四维空间。

Input

输入数据有多组(数据组数不超过 30),到 EOF 结束。

每组输入 4 个数 x, y, z, w 代表四维空间的尺寸(1 <= x, y, z, w <= 30)。

接下来的空间地图输入按照 x, y, z, w 轴的顺序依次给出,你只要按照下面的坐标关系循环读入即可。

for 0, x-1

    for 0, y-1

        for 0, z-1

            for 0, w-1

保证 "S" 和 "E" 唯一。

Output

对于每组数据,输出一行,到达魔戒所需的最短时间。

如果无法到达,输出 "WTF"(不包括引号)。

Sample

Input 

2 2 2 2
..
.S
..
#.
#.
.E
.#
..
2 2 2 2
..
.S
#.
##
E.
.#
#.
..

Output 

1
3
#include <iostream>
#include<bits/stdc++.h>
#define ll long long
const int N = 35;
using namespace std;

int A,B,C,D;
char mp[55][55][55][55];
bool vis[55][55][55][55];
int dirx[]= {0,0,0,0,0,0,1,-1};
int diry[]= {0,0,0,0,1,-1,0,0};
int dirz[]= {0,0,1,-1,0,0,0,0};
int dirw[]= {1,-1,0,0,0,0,0,0};
int flag;
int aa,bb,cc,dd;

struct node
{
    int x;
    int y;
    int z;
    int w;
    int sum;
};
int judge(int x,int y,int z,int w)
{
    if (x>=0&&x<A&&y>=0&&y<B&&z>=0&&z<C&&w>=0&&w<D&&vis[x][y][z][w]==0&&mp[x][y][z][w]!='#')
        return 1;
    return 0;
}
void bfs(int aa,int bb,int cc,int dd)
{
    queue<node>Q;
    node a;
    a.x=aa;
    a.y=bb;
    a.z=cc;
    a.w=dd;
    a.sum=0;
    vis[aa][bb][cc][dd]=1;
    Q.push(a);
    flag=1;
    while (!Q.empty())
    {
        a=Q.front();
        Q.pop();

        if (mp[a.x][a.y][a.z][a.w]=='E')
        {
            printf ("%d\n",a.sum);
            flag=0;
            break;

        }
        for (int i=0; i<8; i++)
        {
            node b;
            b=a;
            b.x+=dirx[i];
            b.y+=diry[i];
            b.z+=dirz[i];
            b.w+=dirw[i];
            if (judge(b.x,b.y,b.z,b.w))
            {
                b.sum++;
                vis[b.x][b.y][b.z][b.w]=1;
                Q.push(b);
            }
        }
    }
    if (flag)
        printf ("WTF\n");
}
int main ()
{
    while(cin>>A>>B>>C>>D)
    {
        getchar();
        for (int i=0; i<A; i++)
        {
            for (int j=0; j<B; j++)
            {
                for (int k=0; k<C; k++)
                {
                    for(int l=0; l<D; l++)
                    {
                        cin>>mp[i][j][k][l];
                        if (mp[i][j][k][l]=='S')
                        {
                            aa=i;
                            bb=j;
                            cc=k;
                            dd=l;
                        }
                    }
                    getchar();
                }
            }
        }
        memset(vis,0,sizeof(vis));
        bfs(aa,bb,cc,dd);
    }

    return 0;
}

 

N - New Game

Description

New game是在一个M*M的特殊棋盘(棋盘的第i行都标上了数字i)上进行的新式游戏。给定一个数字N,要求选手把一个棋子从左上角(1,1)移到右下角(M,M),移动时只能往右或往下。要求移动后经过的数字和为N,且拐弯的次数最少。

如果对给出的N,选手不能找出移动方案使得经过的数字和为N或找出的路径拐弯次数不是最少,选手就输了。所以,选手一定千方百计要找出满足条件的路径!!

Input

两个正整数M,N(其中M<=16),数据保证有解。

Output

最少拐弯数。

Sample

Input 

4 22

Output 

1
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n,m;
int max1=INT_MAX;
int flag1=0;
void dfs(int x,int y,int sum,int num,int flag)
{
    if(x==m&&y==m&&sum==n)
    {
        max1=min(max1,num);
        return;
    }
    if(sum>n||x>m||y>m)
    {
        return;
    }
    if(flag==0)
    {
       dfs(x+1,y,sum+x+1,num,1);
       dfs(x,y+1,sum+x,num,-1);
    }
    else if(flag==1)
    {
       dfs(x+1,y,sum+x+1,num,1);
       dfs(x,y+1,sum+x,num+1,-1);
    }
    else
    {
       dfs(x+1,y,sum+x+1,num+1,1);
       dfs(x,y+1,sum+x,num,-1);
    }
    return;

}
int main()
{
    scanf("%d %d",&m,&n);
    dfs(1,1,1,0,0);
    printf("%d\n",max1);
    return 0;
}

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SDUT--OJ《数据结构与算法》实践能力专题训练6 图论 的相关文章

  • C语言/C++实现栈操作

    一 栈的概念 栈是一种常用的数据结构 它遵循先入后出 Last In First Out LIFO 的原则 栈的操作只在栈的一端进行 该端被称为栈顶 而另一端称为栈底 栈的基本操作包括压栈 入栈 push 和弹栈 出栈 pop 分别用于将元
  • 数据库多维迭代算法

    关键词 数据库 迭代 递归 多维 一 两种传统的数据库迭代结构算法 对于数据库的迭代结构 有两种传统的算法 递归算法和边界算法 比如对于下面图1的结构 图1 递归算法的数据结构如表1所示 节点id 节点值 父节点id 1 1111 2 3
  • Mysql 数据库

    数据库基础 1 什么是数据库 用来存储数据 数据库可在硬盘及内存中存储数据 数据库与文件存储数据的区别 数据库本质也是通过文件来存储数据 数据库的概念就是系统的管理存储数据的文件 数据库介绍 本质就是存储数据的C S架构的socket套接字
  • 树06--二叉树中和为某一值的路径

    树06 二叉树中和为某一值的路径 jz24 题目概述 解析 参考答案 注意事项 说明 题目概述 算法说明 输入一颗二叉树的根节点和一个整数 按字典序打印出二叉树中结点值的和为输入整数的所有路径 路径定义为从树的根结点开始往下一直到叶结点所经
  • 一文弄懂循环链表、双向链表、静态链表

    循环链表 双向链表 静态链表 三遍定律 理解了单链表本文的理解易如反掌 单链表请点击这里 理解了单链表本文的理解易如反掌 单链表请点击这里 理解了单链表本文的理解易如反掌 单链表请点击这里 1 循环链表 将单链表中终端结点的指针端由空指针改
  • Hash table and application in java

    查找的效率取决于在查找是比较的次数 次数越少效率越高 反之越低 最理想的情况是无需比较 一次存取便能找到所查找的记录 根据对应关系f找到给定值K的像f K hash function 应运而生 由此思想建的表称为hash table 集合h
  • PCL—低层次视觉—点云分割(RanSaC)

    点云分割 点云分割可谓点云处理的精髓 也是三维图像相对二维图像最大优势的体现 不过多插一句 自Niloy J Mitra教授的Global contrast based salient region detection出现 最优分割到底鹿死
  • 如何根据链表节点数据大小对链表节点进行排序

    对链表排序有两种方法 1 比较了两个节点的大小后 对指针进行改变 从而交换节点的顺序 2 比较了两个节点的大小后 只交换数据域 而不改变指针 从而交换节点的顺序 第二种办法比较简单 本文主要对第二种方法进行讲解 链表节点排序算法 采用 冒泡
  • Python 实现列队

    1 列队定义 队列是项的有序结合 其中添加新项的一端称为队尾 移除项的一端称为队首 当一个元素从队尾进入队列时 一直向队首移动 直到它成为下一个需要移除的元素为止 最近添加的元素必须在队尾等待 集合中存活时间最长的元素在队首 这种排序成为
  • UE4命令行使用,解释

    命令行在外部 从命令行运行编辑项目 1 导航到您的 LauncherInstall VersionNumber Engine Binaries Win64 目录中 2 右键单击上 UE4Editor exe 的可执行文件 并选择创建快捷方式
  • 链表面试题(一):反转链表的算法实现

    关于链表的考察 链表是面试里面经常涉及到的考点 因为链表的结构相比于Hashmap Hashtable Concurrenthashmap或者图等数据结构简单许多 对于后者更多面试的侧重点在于其底层实现 比如Hashmap中Entry
  • Unique Binary Search Trees -- LeetCode

    原题链接 http oj leetcode com problems unique binary search trees 这道题要求可行的二叉查找树的数量 其实二叉查找树可以任意取根 只要满足中序遍历有序的要求就可以 从处理子问题的角度来
  • 堆栈01--用两个栈实现队列

    堆栈01 用两个栈实现队列 jz05 题目概述 解析 参考答案 注意事项 说明 题目概述 算法说明 用两个栈来实现一个队列 完成队列的Push和Pop操作 队列中的元素为int类型 测试用例 队列先进先出 输入 1 2 输出 1 2 解析
  • 浮生六记

    浮生六记 目录 浮生六记卷一 闺房记乐 002 浮生六记卷二 闲情记趣 015 浮生六记卷三 坎坷记愁 022 浮生六记卷四 浪游记快 034 浮生六记 2 浮生六记卷一 闺房记乐 余生乾隆癸未冬十一月二十有二日 正值太平盛世 且在 衣冠之
  • 机器学习算法GBDT的面试要点总结-上篇

    1 简介 gbdt全称梯度提升决策树 在传统机器学习算法里面是对真实分布拟合的最好的几种算法之一 在前几年深度学习还没有大行其道之前 gbdt在各种竞赛是大放异彩 原因大概有几个 一是效果确实挺不错 二是即可以用于分类也可以用于回归 三是可
  • 区块链中的哈希算法

    区块链中的密码学 密码学在区块链中的应用主要有两个 哈希算法与非对称加密算法 这次主要对哈希算法进行详细的说明 哈希算法 哈希算法的特点有 1 输入可以为任意大小的字符串 2 产生固定大小的输出 3 可以在合理的时间内算出输出值 若要满足密
  • 【数据结构入门精讲 | 第二篇】一文讲清算法复杂度

    上篇文章中我们引入了算法 数据结构 数据类型等概念 而要想衡量一个算法与数据结构是否为优质的 就需要一个衡量标准 这个衡量标准也是在我们实现一个好的算法时要遵循的原则 目录 基本概念 渐进性态 渐进性态数学表征 算法复杂度的运算 顺序搜索算
  • 【数据结构】双链表的定义和操作

    目录 1 双链表的定义 2 双链表的创建和初始化 3 双链表的插入节点操作 4 双链表的删除节点操作 5 双链表的查找节点操作 6 双链表的更新节点操作 7 完整代码 嗨 我是 Filotimo 很高兴与大家相识 希望我的博客能对你有所帮助
  • 【数据结构】单链表的定义和操作

    目录 1 单链表的定义 2 单链表的创建和初始化 3 单链表的插入节点操作 4 单链表的删除节点操作 5 单链表的查找节点操作 6 单链表的更新节点操作 7 完整代码 嗨 我是 Filotimo 很高兴与大家相识 希望我的博客能对你有所帮助
  • C++ AVL树(四种旋转,插入)

    C AVL树 四种旋转 插入 一 AVL树的概念及性质 二 我们要实现的大致框架 1 AVL树的节点定义 2 AVL树的大致框架 三 插入 1 插入逻辑跟BST相同的那一部分 2 修改平衡因子

随机推荐