题面
http://darkbzoj.tk/problem/1077
题解
$Floyed$把砝码看成点,把差值看成边,维护最大的差值和最小的差值,用松弛操作更新即可。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 55 #define ri register int using namespace std; int dmx[N][N],dmi[N][N]; int n,a,b; char ch[N]; int main(){ scanf("%d %d %d",&n,&a,&b); for (ri i=1;i<=n;i++) { scanf("%s",ch+1); for (ri j=1;j<=n;j++) { if (ch[j]=='=') dmi[i][j]=dmx[i][j]=0; else if (ch[j]=='+') dmx[i][j]=2,dmi[i][j]=1; else if (ch[j]=='-') dmx[i][j]=-1,dmi[i][j]=-2; else dmx[i][j]=2,dmi[i][j]=-2; } } for (ri k=1;k<=n;k++) for (ri i=1;i<=n;i++) for (ri j=1;j<=n;j++) { if (k==i || i==j || k==j) continue; dmx[i][j]=min(dmx[i][j],dmx[i][k]+dmx[k][j]); dmi[i][j]=max(dmi[i][j],dmi[i][k]+dmi[k][j]); } int ans1=0,ans2=0,ans3=0; for (ri i=1;i<=n;i++) for (ri j=i+1;j<=n;j++) { if (i==a || i==b || j==a || j==b) continue; if (dmi[a][i]>dmx[j][b] || dmi[a][j]>dmx[i][b]) ans1++; if (dmx[a][i]<dmi[j][b] || dmx[a][j]<dmi[i][b]) ans3++; if (dmx[a][i]==dmi[a][i] && dmx[j][b]==dmi[j][b] && dmi[a][i]==dmx[j][b] ||dmx[a][j]==dmi[a][j] && dmx[i][b]==dmi[i][b] && dmx[a][j]==dmi[i][b]) ans2++; } printf("%d %d %d ",ans1,ans2,ans3); return 0; }