题意:给一个 n*m 的矩阵,问是否能够给每行乘以一个数 Xi,给每列除以一个数 Yj(两行两列之间可以不同),使得最后矩阵中所有元素的值在区间 [L,U] 内
思路:这里的话有除法不好处理,所以两边直接取对数,转化为d[ai]>=d[bi]+log(l/cij),d[bj]>=d[ai]-log(r/cij)这样求最长路或者求最短路也是可以的,代码里面用的是求最短路的方法,然后只是找环的话用DFS会比BFS快很多,直接BFS的话会超时
#include<bits/stdc++.h>
using namespace std;
const int maxn = 805;
vector<pair<int,double> >e[maxn];
/*struct Edge
{
int v,net;
double w;
}edge[maxn*maxn*2];
int cnt,head[maxn];*/
double d[maxn];
int inq[maxn],n,m;
int num[maxn];
/*void init()
{
cnt = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,double w)
{
edge[cnt].v=v,edge[cnt].w=w;
edge[cnt].net=head[u];
head[u]=cnt++;
}*/
bool dfs(int u)
{
//if(inq[u])return true;
inq[u]=1;
for(int i = 0;i<e[u].size();i++)
// for(int i = head[u];i!=-1;i=edge[i].net)
{
int v = e[u][i].first;
// int v = edge[i].v;
// double w = edge[i].w;
if(d[v]>d[u]+e[u][i].second)
// if(d[v]>d[u]+w)
{
d[v]=d[u]+e[u][i].second;
// if(++num[v]>n+m)return true;
//d[v]=d[u]+e[u][i].second;
if(inq[v] || dfs(v))
return true;
}
}
inq[u]=0;
return false;
}
bool spfa()
{
memset(inq,0,sizeof(inq));
for(int i = 0;i<=n+m;i++)
d[i]=1e8;
d[0]=0;
//memset(d,0,sizeof(d));
for(int i = 0;i<=n+m;i++)
if(dfs(i))
return true;
return false;
}
int main()
{
int l,r;
while(scanf("%d%d%d%d",&n,&m,&l,&r)!=EOF)
{
//init();
for(int i = 0;i<=n+m+1;i++)
e[i].clear();
for(int i = 1;i<=n;i++)
for(int j = 1;j<=m;j++)
{
int x;
scanf("%d",&x);
// addedge(i,j+n,-log(1.0*l/x));
// addedge(j+n,i,log(1.0*r/x));
e[i].push_back(make_pair(j+n,-log(1.0*l/x)));
e[j+n].push_back(make_pair(i,log(1.0*r/x)));
}
for(int i = 1;i<=n+m;i++)
// addedge(i,0,0);
e[i].push_back(make_pair(0,0));
if(spfa())
printf("NO\n");
else
printf("YES\n");
}
}