2012-08-29 13:07:10Morris

[UVA][SCC] 10731 - Test

Problem E: Test

A vocational preference test, unlike an aptitude test, seeks to identify careers that the candidate might find satisfying. Based on the answers to a slew of seemingly inane multiple-choice questions like the one below, the test determines which occupations suit the candidate's personality.
   Which would you rather spend an afternoon doing?

   (a) feeding chickens
   (b) driving a race car
   (c) watching The Simpsons on TV
   (d) suntanning
   (e) building a dog house
Each question asks the candidate to express a preference from among five activities, selected from a common larger set. That is, activities like feeding chickens or suntanning are likely to appear in several different questions.

If a candidate answers A in a question containing A, B, C, D, E as alternatives, this choice indicates a preference for A over each of B, C, D, E. Also, if one answer indicates a preference for X over Y and one or more other answers indicate a preference for Y over Z, the combined set of answers indicates a preference for X over Z.

The candidate may provide contradictory answers; that is, the answers may indicate a preference for X over Y and also for Y over X. These contradictions indicate inconsistency, a personalitiy attribute that may suggest a career in politics or used auto sales.

Given a set of answers to a vocational preference test, you are to partition the activities into the minimal number of sets such that, for each pair within a given set, the answers indicate a contradictory preference.

The input contains several test cases followed by a line containing 0. Each case begins with n, the number of questions in the test. n lines follow, each containing the names of five distinct activities, followed by the candidate's answer - one of the five alternatives. Each activity is named by a single upper case letter.

For each test case, output the sets, one per line. Output the elements of each set in alphabetical order, and output the sets in alphabetical order by their least element. The sets should together contain exactly the set of activities that appear in the input. Leave an empty line between test cases.

Sample Input

4
A B C D E C
F C H I J J
K B H I F I
K C E B J K
0

Output for Sample Input

A
B
C
D
E
F
H
I J K

Gordon V. Cormack


題目意思 : 以範例輸入來說,
當選項中有 ABCDE 時, 優先選 C, FCHIJ 時 選 J,
那麼你可以想成 C 優先於 A, ... 等,
最後找出最少的集合數量, 每個集合做決策時, 必須是矛盾的情況
做法 : 做成一張有向圖, 找出 SCC, 也就是矛盾情況


#include <cstdio>
#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
#define maxN 100
using namespace std;
vector<int> g[maxN];
set<string> ans;
int vfind[maxN], findIdx;
int stk[maxN], stkIdx;
int in_stk[maxN], visited[maxN];
int scc(int nd) {
    in_stk[nd] = visited[nd] = 1;
    stk[++stkIdx] = nd;
    vfind[nd] = ++findIdx;
    int mn = vfind[nd];
    for(vector<int>::iterator it = g[nd].begin();
        it != g[nd].end(); it++) {
        if(!visited[*it])
            mn = min(mn, scc(*it));
        if(in_stk[*it])
            mn = min(mn, vfind[*it]);
    }
    if(mn == vfind[nd]) {
        string tmp = "";
        do {
            tmp += (stk[stkIdx]+'A');
            in_stk[stk[stkIdx]] = 0;
        } while(stk[stkIdx--] != nd);
        sort(tmp.begin(), tmp.end());
        ans.insert(tmp);
    }
    return mn;
}
int main() {
    int n, i, j, first = 0;
    char x[4], y[5][4];
    while(scanf("%d", &n) == 1 && n) {
        int app[26] = {};
        for(i = 0; i < 26; i++) {
            g[i].clear();
            visited[i] = in_stk[i] = 0;
        }
        for(i = 0; i < n; i++) {
            for(j = 0; j < 5; j++)
                scanf("%s", y[j]);
            scanf("%s", x);
            app[x[0]-'A'] = 1;
            for(j = 0; j < 5; j++) {
                app[y[j][0]-'A'] = 1;
                if(y[j][0] != x[0]) {
                    g[y[j][0]-'A'].push_back(x[0]-'A');
                }
            }
        }
        ans.clear();
        for(i = 0; i < 26; i++) {
            if(!visited[i] && app[i]) {
                findIdx = stkIdx = 0;
                scc(i);
            }
        }
        if(first)
            puts("");
        first = 1;
        for(set<string>::iterator it = ans.begin();
            it != ans.end(); it++) {
            printf("%c", (*it)[0]);
            for(int j = 1; j < (*it).length(); j++)
                printf(" %c", (*it)[j]);
            puts("");
        }
    }
    return 0;
}