THE MATRIX PROBLEM
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8960 Accepted Submission(s): 2304
Each case includes two parts, in part 1, there are four integers in one line, N,M,L,U, indicating the matrix has N rows and M columns, L is the lowerbound and U is the upperbound (1<=N、M<=400,1<=L<=U<=10000). In part 2, there are N lines, each line includes M integers, and they are the elements of the matrix.
lcy | We have carefully selected several similar problems for you: 3665 3669 3667 3664 3663
对于一个n*m的矩阵W~想问是否有长的为n的序列a和长度为m的序列b ~~存在对任意L<=W[i][j]*a[i]/b[j]<=U;
一眼望去就知道这是一道~关于构图加spfa判断负环的差分约束~但是刚开始根本不知道怎样构图(话说对于图论一直都是构图难~只要勾完图一个函数就出来~)~ 之后发现只要取对数~就会使式子变成::
log(L)-log(W[i][j])<=log(a[i])-log(b[j])<=log(U)-log(W[i][j]);
将每个log(a[i])和log(b[j])看成点~这里我是将j=j+n~让点不重复~然后你跑一个最短路就好了;
结果就是我T了~~囧~感觉这道题非要用A_Star算法??
感觉就很烦~~于是找了找资料~发现了两个关于spfa的优化~~SLF和LLL(我用了SLF这里,有兴趣可以看https://blog.csdn.net/oranges_c/article/details/64124235);
我现在用的就是SLF~~SLF需要用到双端队列deque~这个存在于<queue>里面;大意就是每次插入~如果这个数t的距离大于队列的第一个数的距离~就把他插到队首~否则插到队尾~~!!这里一定要注意在队列为空时候的处理!!;
这样优化后就能过了~其实我觉得SLF和A_*在意义上感觉差的不大~像是简化版本??
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include<cstring>
using namespace std;
#define inf 0x3f3f3f3f
struct ***
{
int to, ne;
double len;
}ed[500000];
double d[50000];
int cnt = 0;
int head[50000];
void add(int from, int to, double len)
{
ed[cnt].len = len;
ed[cnt].to = to;
ed[cnt].ne = head[from];
head[from] = cnt++;
}
int a, b, mi, ma;
bool vis[50000];
int time[50000];
int spfa()
{
deque<int>q;
q.push_front(0);
vis[0] = 1;
d[0]=0;
time[0]=1;
while (!q.empty())
{
int t = q.front();//双端队列
q.pop_front();//双端队列的插入弹出有他独特的函数~需要看下;
vis[t] = 0;
for (int s = head[t]; ~s; s = ed[s].ne)
{
if (d[ed[s].to]>d[t] + ed[s].len)
{
d[ed[s].to] = d[t] + ed[s].len;
if (!vis[ed[s].to])
{
vis[ed[s].to] = 1;
if (++time[ed[s].to]>=a + b)
{
return 0;
}
if(!q.empty())//注意队列为空时的处理
{
if(d[ed[s].to]<d[q.front()])
{
q.push_front(ed[s].to);
}
else
{
q.push_back(ed[s].to);
}
}
else
{
q.push_front(ed[s].to);
}
}
}
}
}
return 1;
}
void init()
{
memset(head,-1,sizeof(head));
memset(vis, 0, sizeof(vis));
memset(time, 0, sizeof(time));
cnt = 0;
memset(d, inf, sizeof(d));
}
int main()
{
int m[500][500];
while (scanf("%d%d%d%d", &a, &b, &mi, &ma)!=EOF)
{
init();
for (int s = 1; s <= a; s++)
{
for (int e = 1; e <= b; e++)
{
scanf("%d", &m[s][e]);
add(s, a + e, log(ma) - log(m[s][e]));//建图
add(a + e, s, log(m[s][e]) - log(mi));
}
}
for (int s = 1; s <= a + b; s++)//建立超级源点
{
add(0, s, 0);
}
if (spfa())
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}