[SCOI2008]天平
题目链接:https://www.luogu.com.cn/problem/P2474
题解:
设
d
i
s
1
[
i
]
[
j
]
dis1[i][j]
dis1[i][j]代表
j
−
i
≤
d
i
s
1
[
i
]
[
j
]
j-i\le dis1[i][j]
j−i≤dis1[i][j],
d
i
s
2
[
i
]
[
j
]
dis2[i][j]
dis2[i][j]代表
j
−
i
≥
d
i
s
2
[
i
]
[
j
]
j-i\ge dis2[i][j]
j−i≥dis2[i][j]。
初始化:
若str[i][j] == ‘+’ , dis1[i][j] = -2, dis2[i][j] = 1;
若str[i][j] == ‘-’ , dis1[i][j] = -1, dis2[i][j] = 2;
若str[i][j] == ‘=’, dis1[i][j] = 0, dis2[i][j] = 0;
否则 dis1[i][j] = 2, dis2[i][j] = -2;
Floyd对dis1跑最短路, dis2跑最长路。
枚举右边的两个砝码,设编号分别为i,j。
左边重,则 a+b>i+j,则
d
i
s
2
[
a
]
[
i
]
>
d
i
s
1
[
j
]
[
b
]
∣
∣
d
i
s
2
[
b
]
[
i
]
>
d
i
s
1
[
j
]
[
a
]
dis2[a][i]>dis1[j][b] || dis2[b][i]>dis1[j][a]
dis2[a][i]>dis1[j][b]∣∣dis2[b][i]>dis1[j][a]。
右边重,则 a+b<i+j, 则
d
i
s
2
[
i
]
[
a
]
>
d
i
s
1
[
b
]
[
j
]
∣
∣
d
i
s
2
[
i
]
[
b
]
>
d
i
s
1
[
a
]
[
j
]
dis2[i][a]>dis1[b][j] || dis2[i][b]>dis1[a][j]
dis2[i][a]>dis1[b][j]∣∣dis2[i][b]>dis1[a][j]。
一样重,则 a+b=i+j,则
(
d
i
s
1
[
a
]
[
i
]
=
=
d
i
s
2
[
a
]
[
i
]
,
d
i
s
1
[
j
]
[
b
]
=
=
d
i
s
2
[
j
]
[
b
]
,
d
i
s
1
[
a
]
[
i
]
=
=
d
i
s
1
[
j
]
[
b
]
)
(dis1[a][i] == dis2[a][i] , dis1[j][b]==dis2[j][b] , dis1[a][i] == dis1[j][b])
(dis1[a][i]==dis2[a][i],dis1[j][b]==dis2[j][b],dis1[a][i]==dis1[j][b])或
(
d
i
s
1
[
a
]
[
j
]
=
=
d
i
s
2
[
a
]
[
j
]
,
d
i
s
1
[
i
]
[
b
]
=
=
d
i
s
2
[
i
]
[
b
]
,
d
i
s
1
[
a
]
[
j
]
=
=
d
i
s
1
[
i
]
[
b
]
)
(dis1[a][j] == dis2[a][j] , dis1[i][b]==dis2[i][b] , dis1[a][j] == dis1[i][b])
(dis1[a][j]==dis2[a][j],dis1[i][b]==dis2[i][b],dis1[a][j]==dis1[i][b])。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<set>
#include<vector>
#include<queue>
#include<iterator>
#include<string>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<LL, int> P;
const int maxn = 120;
const int mod = 998244353;
int dis1[maxn][maxn], dis2[maxn][maxn];
char str[maxn][maxn];
int main()
{
int n, a, b, i, j,k;
scanf("%d %d %d", &n, &a, &b);
for(i=1;i<=n;i++)
scanf("%s", str[i]+1);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i == j)dis1[i][j] = dis2[i][j] = 0;
else dis1[i][j] = 2, dis2[i][j] = -2;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if(str[i][j] == '+')dis1[j][i] = -1, dis2[i][j] = 1;
else if(str[i][j] == '-')dis1[i][j] = -1, dis2[j][i] = 1;
else if(str[i][j] == '=') dis1[i][j] = dis1[j][i] = dis2[i][j] = dis2[j][i] = 0;
}
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
dis1[i][j] = min(dis1[i][j], dis1[i][k]+dis1[k][j]);
dis2[i][j] = max(dis2[i][j], dis2[i][k]+dis2[k][j]);
}
int c1, c2, c3, num1, num2, num3;
c1 = c2 = c3 = 0;
for(i=1;i<=n;i++)
if(i!=a && i!=b)
for(j=i+1;j<=n;j++)
if(j != a && j!= b)
{
if(dis2[a][i]>dis1[j][b] || dis2[b][i]>dis1[j][a])c1++;
if(dis2[i][a]>dis1[b][j] || dis2[i][b]>dis1[a][j])c3++;
if((dis1[a][i] == dis2[a][i] && dis1[j][b]==dis2[j][b] && dis1[a][i] == dis1[j][b])||
(dis1[a][j] == dis2[a][j] && dis1[i][b]==dis2[i][b] && dis1[a][j] == dis1[i][b]) )
c2++;
}
printf("%d %d %d\n", c1, c2, c3);
return 0;
}
/*
4 1 2
??-?
???-
+???
?+??
0 0 0
*/