1. 程式人生 > >藍橋杯-歷屆試題-PREV-13-網路尋路

藍橋杯-歷屆試題-PREV-13-網路尋路

ACM模版

描述

描述
描述

題解

很簡單的一道題,但是前天上 java 課老師讓我們練題,給大家出了一道這題,一看資料就知道這個一定是 dfs+鄰接表,然而我沒有跟著專業學 java,倒是主攻的 C/C++,所以寫 C/C++ 版也就分分鐘的事,可是寫 java 版的我好心塞,java沒有指標,猛一下不知道連結串列怎麼寫,我也不會用 java 的類庫,java 滿共學了十天不到,還是一年前自學的,倒是可以看懂,自己寫卻問題百出,由於能力有限,課上花了二十幾分鍾寫了一個鄰接矩陣+dfs 的解法,只能過部分資料,可是鄰接表我就不知道具體語法怎麼實現了,折騰了好久才解決,不太理解 java 的有些錯誤提示,太頭疼了,讓我給同學寫題解,趕鴨子上架……

這裡提供三種程式碼,一種是為了方便大家學習 dfs 的 java 寫的鄰接矩陣+dfs 的解法(程式碼One),只能過部分資料,但是對於學習 dfs 已經足夠了,一種 C/C++寫的鄰接表+dfs 的解法(程式碼 Two),提交 AC 了,還有一種 java 寫的鄰接表+dfs 的解法(程式碼 Three),由於官網現在在維護中,所以就不提交了,本地測試沒問題。

程式碼

One:

package javatest;

import java.util.Scanner;

public class NodeTongXin 
{
    static int N, M;
    static
int graph[][] = new int[1000][1000]; // 鄰接矩陣 static int vis[][] = new int[1000][1000]; // 標識矩陣,標識(i,j)是否用過 static long cnt = 0; // 累加器 private static Scanner input; static void dfs(int st, int step) // 起點,剩餘邊數 { if (step == 0) // 剩餘0條邊後 GG
{ cnt++; // 找到一條路累加器自增 return ; // 結束這一分支,開始回溯 } for (int i = 1; i <= N; i++) // 尋找下一個結點 { if (vis[st][i] == 0 && graph[st][i] != 0 && i != st) // 要求(st,i)未傳輸過,並且連通 { // i和st不能相等,否則就不是一條邊了 vis[st][i] = 1; // 更改邊的使用情況 vis[i][st] = 1; // 無向圖,(i,st)也得更新 dfs(i, step - 1); // 遞迴,深入下一層查詢,用最新找到的結點為起點深入,剩餘邊數減一 vis[st][i] = 0; // 回溯過程,需要將深入查詢之前更改的使用狀態還原 vis[i][st] = 0; // 同上 } } } public static void main(String[] argv) { input = new Scanner(System.in); N = input.nextInt(); M = input.nextInt(); int a, b; for (int i = 0; i < M; i++) // 一共M條邊 { a = input.nextInt(); b = input.nextInt(); graph[a][b] = 1; // (a,b)連通 graph[b][a] = 1; // 無向圖,(b,a)也連通 } for (int i = 1; i <= N; i++) // 列舉所有結點,作為起點開始深度搜索 { dfs(i, 3); // 初始剩餘三條邊 } System.out.println(cnt); // 輸出累加器結果即為所有結果 } }

Two:

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int MAXN = 10001;

int n, m, cnt = 0;
vector<int> graph[MAXN];

void dfs(int last, int st, int step)
{
    if (step == 0)
    {
        cnt++;
        return ;
    }
    for (int i = 0; i < graph[st].size(); i++)
    {
        if (graph[st][i] != last)
        {
            dfs(st, graph[st][i], step - 1);
        }
    }
}

int main(int argc, const char * argv[])
{
    cin >> n >> m;

    int a, b;
    for (int i = 0; i < m; i++)
    {
        scanf("%d%d", &a, &b);
        graph[a].push_back(b);
        graph[b].push_back(a);
    }

    for (int i = 1; i <= n; i++)
    {
        dfs(-1, i, 3);
    }

    cout << cnt << '\n';

    return 0;
}

Three:

package javatest;

import java.util.Scanner;

public class NodeTongXin2 
{   
    static class Node                           //  鄰接表結點,實際上是連結串列結點
    {
        int v;                                  //  線段端點
        Node nt;                                //  連結串列的下一個結點

        Node()                                  //  例項化時初始化
        {
            nt = null;
        }

        Node(int v_, Node nt_)                  //  例項化時初始化,過載上一個函式
        {
            v = v_;
            nt = nt_;
        }
    }

    static int N, M;
    static Node graph[] = new Node[10005];      //  申請一個表頭,Node 陣列代表表頭
    static long cnt = 0;                        //  累加器
    private static Scanner input;

    static void dfs(int last, int st, int step) //  上一個點,起點,剩餘邊數
    {
        if (step == 0)                          //  剩餘0條邊後 GG
        {
            cnt++;                              //  找到一條路累加器自增
            return ;                            //  結束這一分支,開始回溯
        }
        Node nd = graph[st].nt;                 //  查詢表頭,找到連結串列起點
        for (; nd != null; nd = nd.nt)          //  遍歷連結串列
        {
            if (nd.v != last)                   //  不能等於上一個結點
            {
                dfs(st, nd.v, step - 1);
            }
        }
    }

    public static void main(String[] argv)
    {
        input = new Scanner(System.in);

        N = input.nextInt();
        M = input.nextInt();

        for (int i = 0; i <= N; i++)
        {
            graph[i] = new Node();              //  例項化物件
        }

        int a, b;
        Node nd = null;
        for (int i = 0; i < M; i++)             //  一共M條邊
        {
            a = input.nextInt();
            b = input.nextInt();
            nd = new Node(b, graph[a].nt);      //  頭插法插入連結串列
            graph[a].nt = nd;                   
            nd = new Node(a, graph[b].nt);
            graph[b].nt = nd;
        }

        for (int i = 1; i <= N; i++)            //  列舉所有結點,作為起點開始深度搜索
        {           
            dfs(-1, i, 3);                      //  初始上一個結點為-1,剩餘三條邊
        }

        System.out.println(cnt);                //  輸出累加器結果即為所有結果
    }
}

註釋只能這麼詳細了,如果還不懂,那我就只能給你們畫圖模擬 dfs 每一步的執行過程了,但是我真心不想這樣,我沒有裝 PS……