# bzoj1077: [SCOI2008]天平

71 篇文章 0 订阅

const int N = 60;
struct Edge {
int v;
Edge *next;
Edge(int v, Edge* next) : v(v), next(next){}
} *Fir1[N], *Fir2[N];
int A, B, n;
char Dat[N][N];
int Fa[N];
int Ans1, Ans2, Ans3;
bool E[N][N];
int Cnt[N];

inline int Find(int x) { return (Fa[x] == x) ? x : Fa[x] = Find(Fa[x]); }
inline void Ins(int u, int v) {
if(E[u][v]) return;
E[u][v] = 1, Fir2[u] = new Edge(v, Fir2[u]), Fir1[v] = new Edge(u, Fir1[v]);
}
inline void Input() {
scanf("%d%d%d", &n, &A, &B), scanf("\n");
For(i, 1, n) Fa[i] = i;
For(i, 1, n) {
For(j, 1, n) {
Dat[i][j] = getchar();
if(Dat[i][j] == '=' && (Find(i) ^ Find(j))) Fa[Find(i)] = Fa[Find(j)];
}
scanf("\n");
}
For(i, 1, n) Fa[i] = Find(i);
For(i, 1, n)
For(j, 1, n)
if(Dat[i][j] == '+' || Dat[j][i] == '-') Ins(Fa[i], Fa[j]);
else if(Dat[i][j] == '-' || Dat[j][i] == '+') Ins(Fa[j], Fa[i]);
//For(i, 1, n) printf("%d\n", Fa[i]);
}

inline int GetMax(int u) {
if(Cnt[u]) return Cnt[u];
int MAX = 0;
for(Edge *p = Fir2[u]; p != NULL; p = p->next) MAX = max(MAX, GetMax(p->v));
return Cnt[u] = MAX + 1;
}
inline int GetMin(int u) {
if(Cnt[u]) return Cnt[u];
int MIN = 4;
for(Edge *p = Fir1[u]; p != NULL; p = p->next) MIN = min(MIN, GetMin(p->v));
return Cnt[u] = MIN - 1;
}

inline void Work(int a1, int a2, int b1, int b2) {
a1 = Fa[a1], b1 = Fa[b1], a2 = Fa[a2], b2 = Fa[b2];
if(a1 > a2) swap(a1, a2);
if(b1 > b2) swap(b1, b2);
if(a1 == b1 && a2 == b2) {
Ans2++;
return;
}
if(a1 == b1) a1 = b1 = n + 1;
if(a1 == b2) a1 = b2 = n + 1;
if(a2 == b1) a2 = b1 = n + 1;
if(a2 == b2) a2 = b2 = n + 1;

bool t1 = 0, t2 = 0, t3 = 0;
Rep(i, 16) {
int d = 0;
clr(Cnt, 0);
d += ((i & 1) ? GetMax(a1) : GetMin(a1)) + ((i & 2) ? GetMax(a2) : GetMin(a2));
d -= ((i & 4) ? GetMax(b1) : GetMin(b1)) + ((i & 8) ? GetMax(b2) : GetMin(b2));
if(d > 0 && (t2 || t3)) return;
if(d == 0 && (t1 || t3)) return;
if(d < 0 && (t1 || t2)) return;
t1 = d > 0, t2 = d == 0, t3 = d < 0;
}
Ans1 += t1, Ans2 += t2, Ans3 += t3;
}

inline void Solve() {
For(i, 1, n)
For(j, i + 1, n)
if(i != A && i != B && j != A && j != B) Work(A, B, i, j);
printf("%d %d %d\n", Ans1, Ans2, Ans3);
}

int main() {
#ifndef ONLINE_JUDGE
SETIO("1077");
#endif
Input();
Solve();
return 0;
}

• 0
点赞
• 0
收藏
觉得还不错? 一键收藏
• 0
评论
02-05
11-03
08-19
08-21
09-29
09-30
09-30
09-30
09-30

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。