首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

HDU 5305 Friends:DFS 枚舉邊的線上/線下分配

     編輯:關於C++

問題描述

有 n ≤ 8 個人,m 對好友關係。每對好友可選「線上」或「線下」模式。要求每個人的線上好友數等於線下好友數。求滿足條件的分配方案數。

解題思路:DFS + 剪枝

因 n ≤ 8,m ≤ 28,總方案數 2^m ≤ 2^28 ≈ 2.6億,直接暴力略大,但可利用對稱性與剪枝大幅優化:

  • 若 m 為奇數,直接返回 0(因每人線上=線下 ⇒ 總邊數為偶)。
  • 若某人總度數為奇數,也無解。
  • DFS 遞歸處理每條邊,嘗試分配為線上/線下,維護每人目前的線上/線下計數,若超過總度數一半則剪枝。
  • 所有邊處理完檢查是否所有滿足條件,計數器加一。

代碼框架

int n, m;
int U[30], V[30]; // 邊列表
int online[10], offline[10], degree[10];
long long ans;

void dfs(int idx) {
    if (idx == m) {
        ans++; return;
    }
    int u = U[idx], v = V[idx];
    // 嘗試線上
    if (online[u] < degree[u]/2 && online[v] < degree[v]/2) {
        online[u]++; online[v]++;
        dfs(idx+1);
        online[u]--; online[v]--;
    }
    // 嘗試線下
    if (offline[u] < degree[u]/2 && offline[v] < degree[v]/2) {
        offline[u]++; offline[v]++;
        dfs(idx+1);
        offline[u]--; offline[v]--;
    }
}

int main() {
    int T; scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&n,&m);
        memset(degree,0,sizeof(degree));
        for (int i=0;i

優化技巧

  • 預先檢查度數奇偶性,快速排除無解情況。
  • 邊的處理順序可影響剪枝效率,通常無需特別排序。
  • 用 long long 存儲答案,防止溢出。

複雜度

最壞情況仍為指數級,但實際運行極快(n≤8 保證)。

總結

HDU 5305 是典型的「小規模圖枚舉 + 剪枝」問題。核心在於將「每人線上=線下」轉化為度數約束,並在 DFS 中實時檢查。掌握此類搜索框架,可解決許多組合計數問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved