搜索问题算法两道 M深度优先搜索/N.朋友圈计算问题

M

输入一个图G,用邻接矩阵存储G,输出G的深度优先搜索序列

G中顶点的值为char型

如图1所示的一个用例为

图1

2 6 7
A B C D E F
A B
A D
B C
C D
C E
D F
E F
A
ABCDFE

如图2所示的一个用例为

图2

3 6 10
A B C D E F
A B 6
B E 3
E F 6
F D 2
D A 5
C A 1
C B 5
C E 6
C F 4
C D 5
B
BACDFE

如图3所示的一个用例为

图3

1 4 5
A B C D
A B 6
A D 5
B C 3
C A 4
C D 2
D
DABC

如图4所示的一个用例为

图4

0 3 3
A B C
A B 
B C 
C A 
B
BCA

用例说明:

(1)第一行三个整数分别为录入的图的类型(0代表有向图 1表示有向网 2表示无向图 3表示无向网)、顶点数、边数或弧数

(2)第二行为录入的各个顶点的值,且接下来建立邻接矩阵的时候也按照这个录入的先后顺序从1到n或从0到n-1和各个顶点的值绑定

(3)第三行到倒数第三行为录入的各条边,每条边的第一个字符为起点,第二个字符为终点,如果是G是网,则接下来的量是需要录入的权值,否则不需要录入权值

(4)倒数第二行为录入的DFS的起点

(5)最后一行为输出的DFS的结果,DFS时候,从起始点开始按照结点的绑定顺序对G进行DFS。如果G是非连通的或非强连通的,则从起始点开始遍历后,按照绑定的顺序从下一个未被访问的结点开始继续DFS,图3给出的用例就是这种情况。

代码:

#include <iostream>

using namespace std;
/*
    1.输入图的类型,顶点数,边数
    2.创建图
    3.根据输入起始点输出图的DFS

*/
typedef  char VerTexType;
typedef int ArcType;

const int MVNum = 200;
const int MaxInt = 1086;
int visit[MVNum];

typedef struct
{
    VerTexType vexs[MVNum];
    ArcType arcs[MVNum][MVNum];
    int vexnum, arcnum;
}Graph;

int getlocate(Graph G, VerTexType v)
{
    //    int i=0;
    for (int i = 0; i < G.vexnum; i++)
        if (G.vexs[i] == v)
            return i;
    return -1;
}

void createG(int m, Graph& G)
{
    cin >> G.vexnum >> G.arcnum;
    for (int i = 0; i < G.vexnum; ++i)
    {
        cin >> G.vexs[i];
        visit[i] = 0;
    }

    for (int i = 0; i < G.vexnum; ++i)
        for (int j = 0; j < G.vexnum; ++j)
            G.arcs[i][j] = 0;
    VerTexType v1, v2;//0-有向图,2-无向图
    for (int k = 0; k < G.arcnum; ++k)
    {
        cin >> v1 >> v2;
        int pos1 = getlocate(G, v1);
        int pos2 = getlocate(G, v2);
        G.arcs[pos1][pos2] = 1;
        if (m == 2)
            G.arcs[pos2][pos1] = 1;
    }
    //    for(int i=0;i<G.vexnum;++i){
    //        for(int j=0;j<G.vexnum;++j)
    //            cout<<G.arcs[i][j]<<"\t";
    //        cout<<endl;
    //    }
}

void createN(int m, Graph& G)
{
    cin >> G.vexnum >> G.arcnum;
    for (int i = 0; i < G.vexnum; ++i)
    {
        cin >> G.vexs[i];
        visit[i] = 0;
    }

    for (int i = 0; i < G.vexnum; ++i)
        for (int j = 0; j < G.vexnum; ++j)
            G.arcs[i][j] = MaxInt;

    VerTexType v1, v2;//1-有向网,3-无向网
    ArcType w;
    for (int k = 0; k < G.arcnum; ++k)
    {
        cin >> v1 >> v2 >> w;
        int pos1 = getlocate(G, v1);
        int pos2 = getlocate(G, v2);
        G.arcs[pos1][pos2] = w;
        if (m == 3)
            G.arcs[pos2][pos1] = w;
    }
}

void DFSG(Graph G, VerTexType u)
{
    cout << u;
    int pos = getlocate(G, u);
    visit[pos] = 1;
    for (int w = 0; w < G.vexnum; w++) {
        if (G.arcs[pos][w] != 0 && visit[w] == 0)
            //            cout<<G.vexs[w];
            DFSG(G, G.vexs[w]);
    }

}

void DFSN(Graph G, VerTexType u)
{
    cout << u;

    int pos = getlocate(G, u);
    //    cout<<" "<<pos<<endl;
    visit[pos] = 1;
    for (int w = 0; w < G.vexnum; w++)
        if (G.arcs[pos][w] != MaxInt && visit[w] == 0)
            DFSN(G, G.vexs[w]);
}
int main()
{
    int m;
    VerTexType v0;
    Graph G;
    cin >> m;
    if (m == 0 || m == 2)
    {
        createG(m, G);
        cin >> v0;
        DFSG(G, v0);
        for (int i = 0; i < G.vexnum; ++i)
        {
            if (visit[i] == 0)
                DFSG(G, G.vexs[i]);
        }
    }
    else if (m == 1 || m == 3)
    {
        createN(m, G);
        cin >> v0;
        DFSN(G, v0);
        for (int i = 0; i < G.vexnum; ++i)
        {
            if (visit[i] == 0)
                DFSG(G, G.vexs[i]);
        }
    }

    return 0;
}

N

有n个人,编号为1~n,给定m个形如{a,b}的二元集,a,b∈{1,2,3,...n},表示a和b之间是好朋友。编写一个程序求朋友圈的个数及各个朋友圈的人数(注意:若x和y之间有路径,则x和y位于一个朋友圈中),每个朋友圈至少2个人,朋友圈人数按递增顺序输出,其中n和m的最大值不超过100。参考用例下表所示:

输入用例

11 8
1 2
2 3
1 3
4 5
7 10
7 9
9 10
8 9

输出用例

3
2  3  4

(1)输入用例的第一行的第一个整数为n的值,第二个整数为m的值,后面m行对应m个二元集。

(2)输出用例的第一行的整数为朋友圈的个数,第二行的各个整数为升序输出的各个朋友圈的人数。

代码:

#include <stdio.h>
#include <stdlib.h>

#define MAXN 100

int n, m;
int graph[MAXN][MAXN];
int visited[MAXN];
void dfs(int node)
{
	visited[node] = 1;
	for (int i = 0; i < n; i++)
	{
		if ((graph[node][i] == 1 || graph[i][node] == 1) && visited[i] == 2)
		{
			dfs(i);
		}
	}

}

int main()
{
	for (int i = 0; i < n; i++)
	{
		visited[i] = 0;
	}
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= m; i++)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		graph[a][b] = 1;
		visited[a] = 2;
		visited[b] = 2;
	}
	int count = 0;
	int size[MAXN];
	size[0] = 0;
	for (int i = 1; i <= n; i++)
	{
		if (visited[i] == 2)
		{
			dfs(i);
			count++;
			int q = 0;
			for (int j = 1; j <= n; j++)
			{
				if (visited[j] == 1)
				{
					q++;
				}
			}
			int f = 0;
			for (int i = 0; i < count; i++)
			{
				f = f + size[i];
			}
			size[count] = q - f;
		}
	}

	printf("%d\n", count);
	for (int i = 0; i < count; i++)
	{
		for (int j = 0; j < count - i - 1; j++)
		{
			if (size[j] > size[j + 1])
			{
				int temp = size[j];
				size[j] = size[j + 1];
				size[j + 1] = temp;
			}
		}
	}
	for (int i = 1; i < count + 1; i++)
	{
		printf("%d ", size[i]);
	}
	printf("\n");

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值