2011-08-26 07:54:34Morris

d429. 第一題: 社團分組 (club)

d429. 第一題: 社團分組 (club)

內容 :

有一個社團,其中的社員間並不完全認識,社長想將社員分組以方便聯繫消
息。該社團聯繫消息的方式是社長只電話通知各組中任一個社員,當一個社員
知道消息後要向同一組中其他認識的社員以電話通知。而社長分組的依據是不
會因為一組中只有一個社員的電話故障,而造成同組中其他人沒有獲知消息。
給定社員間認識的關係,請寫一個程式來找出最少的組別可以達到上述效果。

輸入說明 :

(技術限制:社員編號從正整數1依序表示,例如有三個社員,則以社員1,社
員2,社員3來表示。)
第一行為一正整數N,1 < N < 25,表示社員數目。第二行起每一行表示互相認
識的社員配對,以0表示結束。兩個社員編號間以空白分開,例如1 3 表示社
員1認識社員3,亦表示社員3認識社員1,且出現編號沒有順序性。

輸出說明 :

顯示最少分組數目。

範例輸入 :

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

範例輸出 :

2

提示 :

出處 :

92 (管理:nanj0178)



作法 : 一次 DFS, 標記搜尋的深度, 以及可以返回的最小深度,
藉此找到所有關節點, 然後關節點用 Greedy 去做處理
測資有點弱了, 所以我不曉得, 這樣的做法, 能不能包含所有情況,
就以目前是可以的

/**********************************************************************************/
/*  Problem: d429 "第一題: 社團分組 (club)" from 92                        */
/*  Language: C                                                                   */
/*  Result: AC (1ms, 230KB) on ZeroJudge                                          */
/*  Author: morris1028 at 2011-08-25 23:54:30                                     */
/**********************************************************************************/


#include<stdio.h>
#include<string.h>
#define oo 100000
int map[30][30], used[30], back[30], joint[30], chose[30];
int n, find, Ans;
int min(int x, int y) {
    return x < y ? x : y;
}
int DFS(int now, int last, int depth) {
    int a, back_depth = depth-1, t;
    back[now] = depth, find++;
    for(a = 0; a <= n; a++) {
        if(map[now][a]) {
            if(used[a]) {
                back_depth = min(back_depth, back[a]);
            } else {
                used[a] = 1;
                t = DFS(a, now, depth+1);
                back_depth = min(back_depth, t);
            }
        }
    }
    if(back_depth == depth-1) {
        for(a = 0; a <= n; a++)
            if(map[now][a] && joint[a] == 1 && chose[a] == 1)
                break;
        if(a == n+1)    {Ans++;chose[now] = 1;}
        joint[now] = 1;
    }
    return back_depth;
}
main() {
    int x, y;
    while(scanf("%d", &n) == 1) {
        memset(map, 0, sizeof(map));
        memset(used, 0, sizeof(used));
        memset(chose, 0, sizeof(chose));
        memset(joint, 0, sizeof(joint));
        while(scanf("%d", &x) == 1 && x) {
            scanf("%d", &y);
            map[x][y] = 1, map[y][x] = 1;
        }
        Ans = 0, find = 0, used[1] = 1, DFS(1, 0, 0);
        printf("%d\n", Ans+(n-find));
    }
    return 0;
}