【SCOI2008】天平

题面

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\n",ans1,ans2,ans3);
  return 0;
}

 

posted @ 2019-08-14 19:53  HellPix  阅读(132)  评论(0编辑  收藏  举报