矩阵问题 [差分约束]

矩阵问题 [差分约束]

问题描述

   给出一个n*m的整数矩阵F。矩阵中第i行第j列的元素表示为F[i][j] 1<=i<=n, 1<=j<=m。
   求两个数列A和B,数列A有n个元素:A1,A2,A3…An 。数列B有m个元素:B1,B2,B3…..Bm,
   使得对矩阵中的每个数进行下面的计算之后的结果在[X,Y]之间:
计算操作为:A[i] * F[i][j] / B[j]

输入格式

第一行, 一个整数T(T<=5),表示有T组测试数据
对于每组测试数据:
第一行,四个整数n,m,X,Y
接下来一个n*m的矩阵,数字间以空格做间隔

输出格式

共T行,每行对应一组测试数据的结果:
若能找到满足条件的数列A和B,输出“YES”,否则输出“NO”

提示

1<=N、M<=400,1<=X<=Y<=20000

给出的矩阵中每个数字都是1000以内的正整数。

这道题有不等关系,显然是差分约束。但是如何建图是个很严重的问题。

首先要明确的一点是:差分约束的式子x-y<=k中x,y前的系数都必须是1,而且k必须是常数。(我就是因为这一点没有把式子化简出来,可恶)

题目中F[i][j]和x,y都是常数,所以它们肯定要放在式子的右边。以A[i] * F[i][j] / B[j] <= Y 为例,A[i] / B[j] <= Y / F[i][j]. 变成减法当然是取对数!!!这道题敲个板就完了,所以还是比较简单的。

数组不要开小了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<queue>
#include<cstring>
#define D double
#define E 500000
#define N 1000
using namespace std;
int End[E],Last[E],Next[E],cnt,Pnum,ti[N];
D Len[E],dis[N];bool used[N];
void Init(){
    for(int i=0;i<E;i++)
        {End[i]=Last[i]=Next[i]=0;Len[i]=0;}
    for(int i=0;i<N;i++)used[i]=0,ti[i]=0;
    cnt=0;
}
void Ins(int x,int y,D w){
    End[++cnt]=y,Len[cnt]=w;
    Next[cnt]=Last[x],Last[x]=cnt;
}
bool SPFA(int s){
    for(int i=1;i<=Pnum;i++)dis[i]=(D)1e9;
    queue<int>q;q.push(s);
    dis[s]=0,ti[s]++,used[s]=true;
    while(!q.empty()){
        int u=q.front();q.pop();used[u]=false;
        for(int i=Last[u];i;i=Next[i]){
            int v=End[i];
            if(dis[v]>dis[u]+Len[i]){
                dis[v]=dis[u]+Len[i];
                if(!used[v]){
                    if(++ti[v]>Pnum)return false;
                    used[v]=true,q.push(v);
                }
            }
        }
    }
    return true;
}
int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n,m,x,y;D xx,yy;
        scanf("%d%d%d%d",&n,&m,&x,&y);
        xx=log2(x),yy=log2(y);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                int t;scanf("%d",&t);D tt=log2(t);
                Ins(i,j+n,tt-xx),Ins(j+n,i,yy-tt);
            }
        Pnum=n+m;
        if(SPFA(1))puts("YES");
        else puts("NO");
        Init();
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/arliastark/article/details/80459455