bzoj1077: [SCOI2008]天平

恶心题,代码完全抄袭某神,请无视

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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值