首选把不等式改写一下,对于元素 Xij
L<=Xij*ai/bj<=U
这里是乘法,但是差分约束系统需要加法,所以就取个对数,这样不等式就有了。
这里的数据量比较恐怖,用bellman-ford是要超时的。
这里我用了spfa,然后一个点入队伍超过sqrt(n+m)次(注意转换double),就说明有环。
正常情况下应该是超过n+m次才可判定,但是这里我看网上题解,大多都说sqrt就够了。
估计和图的特殊性有关系。
#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<vector>
#include<queue>
#include<math.h>
using namespace std;
double mat[600][600];
int N,M;
double U,L;
const double eps=1e-3;
double dis[900];
bool inqueue[900];
int cnt[900];
struct node
{
int to;
double w;
};
vector<node> G[900];
void init()
{
for(int i=0;i<900;i++) G[i].clear();
}
bool SPFA()
{
queue<int> Q;
for(int i=0;i<N+M;i++)
{
dis[i]=0;
inqueue[i]=0;
cnt[i]=0;
Q.push(i);
}
while(Q.empty()==false)
{
int now=Q.front();
inqueue[now]=0;
int size=G[now].size();
Q.pop();
for(int i=0;i<size;i++)
{
int to=G[now][i].to;
double w=G[now][i].w;
if(inqueue[to]==0 && dis[to]-(dis[now]+w)>eps)
{
dis[to]=dis[now]+w;
inqueue[to]=1;
cnt[to]++;
if(cnt[to]>sqrt(1.0*(N+M))) return false;
Q.push(to);
}
}
}
return true;
}
int main()
{
while(cin>>N>>M>>L>>U)
{
init();
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
scanf("%lf",&mat[i][j]);
}
}
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
double now=mat[i][j];
node tmp;
tmp.to=i;
tmp.w=log(U)-log(now);
G[N+j].push_back(tmp);
tmp.to=N+j;
tmp.w=log(now)-log(L);
G[i].push_back(tmp);
}
}
bool ans=SPFA();
if(ans==true)
{
printf("YES\n");
}
else printf("NO\n");
}
return 0;
}