山東理工大學網絡擂臺賽——A.五軍之戰

山東理工大學網絡擂臺賽——A.五軍之戰

題目內容

在這裏插入圖片描述
在這裏插入圖片描述

個人AC程序

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int maxn = 2030;
typedef long long ll;
int n, u, v, leafCnt;
bool isVis[maxn];
vector<int> G[maxn];
vector<ll> roads;

#define min(a, b) (a) < (b) ? (a) : (b)

/// C(a, b) = a!/b!/(a-b)!
/// Called : C(leafCnt, 5)
ll getSchamesCount(ll a, ll b)
{
    ll ret = 1;
    for(ll i = 1;i <= b;++i)
    {
        ret *= a;
        ret /= i;
        a--;
    }
    return ret;
}

void dfs(int curPos, ll curLen)
{
    if(1 == (int)G[curPos].size() && 1 != curPos)
    {
        roads.push_back(curLen);
        return ;
    }
    for(int i = 0;i < (int)G[curPos].size();++i)
    {
        int nxtPos = G[curPos][i];
        if(!isVis[nxtPos])
        {
            isVis[nxtPos] = true;
            dfs(nxtPos, curLen + 1);
            isVis[nxtPos] = false;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    isVis[1] = true;
    cin >> n;
    for(int i = 1;i < n;++i)
    {
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for(int i = 2;i <= n;++i)
    {
        if(1 == (int)G[i].size())
        {
            leafCnt++;
        }
    }
    dfs(1, 0);
    sort(roads.begin(), roads.end());
    ll res1 = 0, res2 = 0;
    if(leafCnt > 5)
    {
        res1 = getSchamesCount(leafCnt, 5);
        for(int i = 0;i < 5;++i)
        {
            res2 += roads[i];
        }
    }
    else
    {
        res1 = 1;
        for(int i = 0;i < leafCnt;++i)
        {
            res2 += roads[i];
        }
    }
    cout << res1 << ' ' << res2 << endl;
    return 0;
}

在這裏插入圖片描述

算法分析與設計

這題是一個很簡單的深度優先遍歷的習題,可是我仍是WA了不少次,羞愧啊!html

問題一: 如何計算出方案數?ios

只須要計算有多少個葉子節點 c n t cnt cnt,而後計算 C ( c n t , 5 ) C(cnt, 5) C(cnt,5),若是 c n t < 5 cnt < 5 cnt<5則直接輸出1,由於此時沒有足夠的葉子結點去排兵佈陣。算法

而後此題不要求對組合數取模,說明組合數計算的中間結果不會超過long long,那麼只須要一遍循環計算便可!數組

問題2: 如何計算出有多少個葉子節點?markdown

葉子結點的度爲1,只須要維護一個degree數組就能夠解決,也就是對數組遍歷,若是值爲1則累計增長一個葉子節點。網絡

固然,更好的辦法是利用圖的數據結構,查看鄰接表的鄰接規模,也就是vector的size就能夠判斷是不是葉子節點,由於葉子節點的size必定是1,而除了根節點之外的普通結點必定不是1!數據結構

注意咱們說的除了根節點之外的結點,由於若是這棵樹退化成鏈,則根節點也是度爲1的結點!ide

問題3: 如何計算最短的路徑?atom

這題只須要計算最短的五個(或更少)排兵佈陣的葉子結點到根節點的路徑和,而後根節點的數量確定不超過 n / 2 = 1010 n/2=1010 n/2=1010,因此用數組存下全部葉子節點到根節點的路徑而後排序獲得最短的幾個累計便可!spa

若是排兵佈陣的葉子結點不少,不必定只有五個的時候!就是典型的Top K問題,就維護一個大小爲K的小頂堆,每次插入的時間是 l o g ( n ) log(n) log(n),計算的總時間是 K + l o g ( n ) K+log(n) K+log(n),這要比維護數組排序的 n + n l o g ( n ) n+nlog(n) n+nlog(n)要好不少!

結束語

有想要探討、合做的小夥伴能夠關注我,有問題能夠發郵件給我,個人郵箱是:2329313458@qq.com

相關文章
相關標籤/搜索