背景:
h
e
h
e
.
.
.
hehe...
hehe...
题目传送门:
https://www.luogu.org/problemnew/show/P2474
题意:
有些砝码,两两满足一些关系。有一个天平,现在选出
A
,
B
A,B
A,B砝码,在剩下的砝码中任选两个
x
,
y
x,y
x,y,使得满足
A
+
B
(
>
/
=
/
<
)
x
+
y
A+B(> /=/< )x+y
A+B(>/=/<)x+y分别满足这三种关系的方案数。
思路:
考虑差分约束。
若砝码满足
x
>
y
x>y
x>y,则它们的关系是
x
−
y
≥
1
,
x
−
y
≤
2
x-y≥1,x-y≤2
x−y≥1,x−y≤2;
同理可以算出其它的关系。
那么每两个砝码就存在一些关系,且有最小和最大值,跑一边
f
l
o
y
d
floyd
floyd求最短路,就知道它们的关系。
若
A
+
B
>
x
+
y
A+B>x+y
A+B>x+y,则
A
−
x
A-x
A−x的最小值一定大于
y
−
B
y-B
y−B的最大值;同理可以算出其它的。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,t1,t2,ans1=0,ans2=0,ans3=0;
int ma[60][60],mi[60][60];
int main()
{
char s[60];
scanf("%d %d %d",&n,&t1,&t2);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=n;j++)
{
if(i==j) {ma[i][j]=0,mi[i][j]=0;continue;}
switch(s[j])
{
case '+':ma[i][j]=2,mi[i][j]=1;break;//若x>y,则x-y>=1,x-y<=2
case '-':ma[i][j]=-1,mi[i][j]=-2;break;
case '=':ma[i][j]=0,mi[i][j]=0;break;
case '?':ma[i][j]=2,mi[i][j]=-2;break;
}
}
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j||i==k||j==k) continue;
ma[i][j]=min(ma[i][j],ma[i][k]+ma[k][j]);
mi[i][j]=max(mi[i][j],mi[i][k]+mi[k][j]);
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
if(i==t1||i==t2||j==t1||j==t2) continue;
if(mi[t1][i]>ma[j][t2]||mi[t2][i]>ma[j][t1]) ans1++;//若A+B>i+j,则A-i的最小值一定大于j-B的最大值
if((ma[t1][i]==mi[t1][i]&&ma[j][t2]==mi[j][t2]&&ma[t1][i]==ma[j][t2])
||(ma[t1][j]==mi[t1][j]&&ma[i][t2]==mi[i][t2]&&ma[t1][j]==ma[i][t2])) ans2++;
if(ma[t1][i]<mi[j][t2]||ma[t2][i]<mi[j][t1]) ans3++;
}
printf("%d %d %d",ans1,ans2,ans3);
}