POJ 2912 Rochambeau

并查集应用。

这道题目和 POJ 1182 食物链 非常类似。

枚举所有judge,不处理出现当前judge的round,然后利用食物链的解法判断冲突。就可以找出来最终的judge。

还有一步就是找到judge之后,要得到确定此judge的round数:这个round数就是在枚举的时候,其他人出错的round数的最大值——因为,到这个最大round数时,其他人都被排除,剩下的就是真正的judge



#include <cstdio>
#include <cstring>
const int MAXN = 505;
const int MAXM = 2004;
int set[MAXN], a[MAXN];
struct node {
    int u, v;
    char ch;
} p[MAXM];
/*
    a[x] = 0 =
    a[x] = 1 <
    a[x] = 2 >
*/
int f1[3][3] = {{0, 1, 2}, {2, 0, 1}, {1, 2, 0}};
int f2[3][3] = {{1, 2, 0}, {0, 1, 2}, {2, 0, 1}};
int f3[3][3] = {{2, 0, 1}, {1, 2, 0}, {0, 1, 2}};
int n, m;

int Find_set(int x) {
    if (set[x] == x) return x;
    int t = Find_set(set[x]);
    a[x] = (a[x] + a[set[x]]) % 3;
    return set[x] = t;
}
void Union(int x, int y, char ch) {
    int fx = Find_set(x);
    int fy = Find_set(y);
    set[fx] = fy;
    if (ch == '=') a[fx] = f1[a[x]][a[y]];
    else if (ch == '<') a[fx] = f2[a[x]][a[y]];
    else a[fx] = f3[a[x]][a[y]];
}
void solve() {
    int x, y, fx, fy;
    int err[MAXN];
    memset(err, 0, sizeof(err));

    for (int j=0; j<n; j++) {  //枚举judge
        for (int i=0; i<n; i++)
            set[i] = i, a[i] = 0;

        for (int i=0; i<m; i++) {
            x = p[i].u, y = p[i].v;
            if (x == j || y == j) continue;
            fx = Find_set(x);
            fy = Find_set(y);
            if (fx == fy) {
                if (p[i].ch == '=' && a[x]!=a[y]) {
                    err[j] = i+1; break;
                }
                if (p[i].ch == '<' && (a[x]+2)%3 != a[y]) {
                    err[j] = i+1; break;
                }
                if (p[i].ch == '>' && (a[x]+1)%3 != a[y]) {
                    err[j] = i+1; break;
                }
            } else Union(x, y, p[i].ch);
        }
    }

    int cnt = 0, k, ans = 0;
    for (int i=0; i<n; i++) {
        if (err[i] == 0)  cnt++, k = i;
        if (err[i] > ans) ans = err[i];
    }
    if (cnt == 0) printf("Impossible\n");
    else if (cnt == 1)
        printf("Player %d can be determined to be the judge after %d lines\n", k, ans);
    else printf("Can not determine\n");
}
int main() {
    
    while (scanf("%d %d", &n, &m) == 2) {
        for (int i=0; i<m; i++)
            scanf(" %d%c%d", &p[i].u, &p[i].ch, &p[i].v);
        solve();
    }
    return 0;
}


你可能感兴趣的:(POJ 2912 Rochambeau)