题目意思:
一共有n+m个变量。行有那个x1,x2...xn, 列有m个b1 b2 ..bm;
然后保证 aij位置 l<=aij*xi/bj<=r;
解题思路:
对上面这个试子取对数 那么就形成了 一个典型的差分约束系统了。
每个不等试形成一条从被减数到减数的相应权值的边。
然后构图spfa即可,注意要用邻接表,这个题目容易超时。
还有注意一点:
spfa判断存在负权环:
(1) 单个点入队列的次数大于 sqrt(N) , N代表所有点的个数
(2) 点入队列的次数总和大于 T*N ,据说T一般取2.
《算法导论》里面说构造一个原点,他到其他每个点的边的长度为0,然后再SPFA,
其实直接可以讲所有0~n+m点先直接入队列,然后设置所有长度为0,效果一样
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
const double MAX=0x3f3f3f3f;
int n,m;
double l,r;
struct node
{
int v,nxt;
double w;
}edge[800000];
int head[1000],nume;
void add(int u,int v,double w)
{
edge[nume].v=v;edge[nume].w=w;edge[nume].nxt=head[u];head[u]=nume++;
}
int spfa(){
double dis[1000];
int inque[1000],i;
queue<int >q;
for(i=0;i<=n+m;i++){
dis[i]=0;
inque[i]=0;
q.push(i);
}
int sum=1;
while(!q.empty()){
int temp=q.front();
q.pop();
inque[temp]=0;
for(i=head[temp];i!=-1;i=edge[i].nxt){
int v=edge[i].v;
if(dis[temp]+edge[i].w<dis[v]){
dis[v]=dis[temp]+edge[i].w;
if(!inque[v]){
q.push(v);
inque[v]=1;
sum++;
if(sum>2*(n+m)) return 0;
}
}
}
}
return 1;
}
int main()
{
while(scanf("%d%d%lf%lf",&n,&m,&l,&r)!=EOF){
int i,j;
nume=0;
memset(head,-1,sizeof(head));
// for(i=1;i<=n+m;i++) add(0,i,0);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++){
double temp;
scanf("%lf",&temp);
add(n+j,i,log10(r)-log10(temp));
add(i,n+j,log10(temp)-log10(l));
}
if(spfa()) printf("YES\n");
else printf("NO\n");
}
return 0;
}