圖的遍歷(dfs + bfs) + 最小生成樹(prime) 模板

問題 : 算法7-4,7-5:圖的遍歷——深度優先搜索

時間限制: 1 Sec  內存限制: 32 MB
提交: 12  解決: 12
[提交][狀態]

題目描述

深度優先搜索遍歷類似於樹的先根遍歷,是樹的先根遍歷的推廣。其過程爲:假設初始狀態是圖中所有頂點未曾被訪問,則深度優先搜索可以從圖中的某個頂點v出發,訪問此頂點,然後依次從v的未被訪問的鄰接點出發深度優先遍歷圖,直至圖中所有和v有路徑相通的頂點都被訪問到;若此時圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作爲起始點,重複上述過程,直至圖中所有頂點都被訪問到爲止。

在本題中,讀入一個無向圖的鄰接矩陣(即數組表示),建立無向圖並按照以上描述中的算法遍歷所有頂點,輸出遍歷頂點的順序。

輸入

輸入的第一行包含一個正整數n,表示圖中共有n個頂點。其中n不超過50。

以後的n行中每行有n個用空格隔開的整數0或1,對於第i行的第j個0或1,1表示第i個頂點和第j個頂點有直接連接,0表示沒有直接連接。當i和j相等的時候,保證對應的整數爲0。

輸入保證鄰接矩陣爲對稱矩陣,即輸入的圖一定是無向圖。

輸出

只有一行,包含n個整數,表示按照題目描述中的深度優先遍歷算法遍歷整個圖的訪問頂點順序。每個整數後輸出一個空格,並請注意行尾輸出換行。

樣例輸入

4
0 1 0 1
1 0 0 0
0 0 0 1
1 0 1 0

樣例輸出

0 1 3 2 

模板:

# include <stdio.h>
# include <string.h>

int a[51][51], book[51];

int n;

void dfs(int cur)
{
	printf("%d ", cur);
	
	if (cur == n)
		return;
	
	int k;
	for (k = 0; k < n; k ++)
	{
		if (a[cur][k] == 1 && book[k] == 0)
		{
			book[k] = 1;
			dfs(k);
		}
	}
	return;
}
int main(void)
{
	int i ,j;
	while (~ scanf("%d", &n))
	{
		for (i = 0; i < n; i ++)
			for (j = 0; j < n; j ++)
				scanf("%d", &a[i][j]);
		memset(book, 0, sizeof(book));
		book[0] = 1;
		dfs(0);
	}
	return 0;
}

問題 : 算法7-6:圖的遍歷——廣度優先搜索

時間限制: 1 Sec  內存限制: 32 MB
提交: 13  解決: 10
[提交][狀態]

題目描述

廣度優先搜索遍歷類似於樹的按層次遍歷的過程。其過程爲:假設從圖中的某頂點v出發,在訪問了v之後依次訪問v的各個未曾被訪問過的鄰接點,然後分別從這些鄰接點出發依次訪問它們的鄰接點,並使“先被訪問的頂點的鄰接點”先於“後被訪問的頂點的鄰接點”被訪問,直至圖中所有已被訪問的頂點的鄰接點都被訪問到。若此時圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作爲起始點。重複上述過程,直至圖中所有頂點都被訪問到爲止。

其算法可以描述如下:

在本題中,讀入一個無向圖的鄰接矩陣(即數組表示),建立無向圖並按照以上描述中的算法遍歷所有頂點,輸出遍歷頂點的順序。

輸入

輸入的第一行包含一個正整數n,表示圖中共有n個頂點。其中n不超過50。

以後的n行中每行有n個用空格隔開的整數0或1,對於第i行的第j個0或1,1表示第i個頂點和第j個頂點有直接連接,0表示沒有直接連接。當i和j相等的時候,保證對應的整數爲0。

輸入保證鄰接矩陣爲對稱矩陣,即輸入的圖一定是無向圖。

輸出

只有一行,包含n個整數,表示按照題目描述中的廣度優先遍歷算法遍歷整個圖的訪問頂點順序。每個整數後輸出一個空格,並請注意行尾輸出換行。

樣例輸入

4
0 0 0 1
0 0 1 1
0 1 0 1
1 1 1 0

樣例輸出

0 3 1 2 

模板:

# include <stdio.h>
# include <string.h>
 
int a[51][51], qwe[1501], book[51];
 
int main(void)
{
    int t, c, i, j;
    while (~ scanf("%d", &t))
    {
        memset(book, 0, sizeof(book));
        memset(qwe, 0, sizeof(qwe));
        for (i = 0; i < t; i ++)
            for (j = 0; j < t; j ++)
                scanf("%d", &a[i][j]);
 
        int head = 0, tail = 0;
        qwe[tail] = 0;
        tail ++;
        book[0] = 1;
        int cur, k;
        while (head < tail && tail < t)
        {
            cur = qwe[head];
            for (k = 0; k < t; k ++)
            {
                if (a[cur][k] == 1 && book[k] == 0)
                {
                    qwe[tail] = k;
                    tail ++;
                    book[k] = 1;
                }
                if (tail >= t)
                    break;
            }
            head ++;
        }
        for (i = 0; i < tail; i ++)
            printf("%d ", qwe[i]);
        printf("\n");
    }
    return 0;
}

問題 : 算法7-9:最小生成樹

時間限制: 1 Sec  內存限制: 32 MB
提交: 7  解決: 6
[提交][狀態]

題目描述

最小生成樹問題是實際生產生活中十分重要的一類問題。假設需要在n個城市之間建立通信聯絡網,則連通n個城市只需要n-1條線路。這時,自然需要考慮這樣一個問題,即如何在最節省經費的前提下建立這個通信網。

可以用連通網來表示n個城市以及n個城市之間可能設置的通信線路,其中網的頂點表示城市,邊表示兩個城市之間的線路,賦於邊的權值表示相應的代價。對於n個頂點的連通網可以建立許多不同的生成樹,每一棵生成樹都可以是一個通信網。現在,需要選擇一棵生成樹,使總的耗費最小。這個問題就是構造連通網的最小代價生成樹,簡稱最小生成樹。一棵生成樹的代價就是樹上各邊的代價之和。

而在常用的最小生成樹構造算法中,普里姆(Prim)算法是一種非常常用的算法。以下是其算法的大致結構:

在本題中,讀入一個無向圖的鄰接矩陣(即數組表示),建立無向圖並按照以上描述中的算法建立最小生成樹,並輸出最小生成樹的代價。

輸入

輸入的第一行包含一個正整數n,表示圖中共有n個頂點。其中n不超過50。

以後的n行中每行有n個用空格隔開的整數,對於第i行的第j個整數,如果不爲0,則表示第i個頂點和第j個頂點有直接連接且代價爲相應的值,0表示沒有直接連接。當i和j相等的時候,保證對應的整數爲0。

輸入保證鄰接矩陣爲對稱矩陣,即輸入的圖一定是無向圖,且保證圖中只有一個連通分量。

輸出

只有一個整數,即最小生成樹的總代價。請注意行尾輸出換行。

樣例輸入

4
0 2 4 0
2 0 3 5
4 3 0 1
0 5 1 0

樣例輸出

6

模板:

# include <stdio.h>
# include <string.h>
 
int main(void)
{
    int t, a[51][51], book[51], dis[51];
    while (~ scanf("%d", &t))
    {
        memset(book, 0, sizeof(book));
        int i, j;
        for (i = 1; i <= t; i ++)
            for (j = 1; j <= t; j ++)
                {
                    scanf("%d", &a[i][j]);
                    if(i != j && a[i][j] == 0)
                        a[i][j] = 99999999;
                }
        int count = 0, sum = 0;
        book[1] = 1;
        count ++;
        int min;
        for (i = 1; i <= t; i ++)
            dis[i] = a[1][i];
 
        while (count < t)
        {
            min = 99999999;
            for (i = 1; i <= t; i ++)
            {
                if (book[i] == 0 && dis[i] < min)
                {
                    min = dis[i];
                    j = i;
                }
            }
            book[j] = 1;
            count ++;
            sum += dis[j];
            for (int k = 1; k <= t; k ++)
            {
                if (book[k] == 0 && dis[k] > a[j][k])
                    dis[k] = a[j][k];
            }
        }
        printf("%d\n", sum);
    }
    return 0;
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章