P2474 [SCOI2008]天平
不得不说人家省选题目出的就是有水平
开始一直没有搞懂题目到底什么意思 这句话是关键:只有结果保证惟一的选法才统计在内
也就是左边有很多种可能性 右边选出来有很多种可能性 必须是左边严格大于右边(可能性不相交)c1++
同理 那这样就好理解了 因为是大小关系 想到差分约束 因为我们要严格大于或者小于 所以要求最长路和最短路
之后枚举就行
#include
#include
#include
#include
#include
#include
using namespace std;
int n,s1,s2;
int dx[55][55],dn[55][55];
int main()
{
scanf("%d%d%d",&n,&s1,&s2);
char a[60];
for(int i=1;i<=n;i++){
scanf("%s",a);
for(int j=0;j=1;
}else if(a[j]=='-'){
dx[i][j+1]=-1; dn[i][j+1]=-2; //i-j<=-1;i-j>=-2;
}else {
dx[i][j+1]=2; dn[i][j+1]=-2; //i-j<=2; i-j>=-2;
}
}
}
for(int k=1;k<=n;k++) //Floyd
for(int i=1;i<=n;i++) {
if(i==k) continue;
for(int j=1;j<=n;j++){
if(i==k || i==j) continue;
dx[i][j]=min(dx[i][j],dx[i][k]+dx[k][j]);//上界求最短路
dn[i][j]=max(dn[i][k]+dn[k][j],dn[i][j]);//下界求最长路
}
}
int c1=0,c2=0,c3=0;
for(int i=1;i<=n;i++){ //暴力枚举所有可能性
if(i==s1 || i==s2) continue;
for(int j=1;jdx[j][s2] || dn[s2][i]>dx[j][s1])
c1++; //s1-i的最小值大于j-s2的最大值==>s1+s2>i+j
if(dn[i][s1]>dx[s2][j] || dn[i][s2]>dx[s1][j])
c3++; //同理:i-s1>s2-j ==> i+j>s1+s2
if((dn[s1][i]==dx[s1][i] && dn[j][s2]==dx[j][s2] && dn[s1][i]==dn[j][s2]) ||
(dn[s1][j]==dx[s1][j] && dn[i][s2]==dx[i][s2] && dn[s1][j]==dn[i][s2]))
c2++; //关系确定且满足的点
}
}
printf("%d %d %d",c1,c2,c3);
return 0;
}