您的位置:首页 > 其它

HDU 3666 THE MATRIX PROBLEM(差分约束 + spfa 深搜判环)

2013-07-17 09:07 681 查看
题目链接:Click here~~

题意:

给一个 n*m 的矩阵,问是否能够给每行乘以一个数 Xi,给每列除以一个数 Yj(两行两列之间可以不同),使得最后矩阵中所有元素的值在区间 [L,U] 内。

解题思路:

取对数后很容易就可以转成差分约束的不等式了。但这题用 spfa 队列判环会超时。

于是在网上学习了一个新的姿势,就是用类似 spfa 的思想深搜来判环,300+MS,效率好高啊。

#include <queue>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

template<int N,int M>
struct Graph
{
    int top;
    struct Vertex{
        int head;
    }V
;
    struct Edge{
        int v,next;
        double w;
    }E[M];
    void init(){
        memset(V,-1,sizeof(V));
        top = 0;
    }
    void add_edge(int u,int v,double w){
        E[top].v = v;
        E[top].w = w;
        E[top].next = V[u].head;
        V[u].head = top++;
    }
};

const int N = 8e2 + 5;

Graph<N,N*N> g;

double d
;

bool inq
;

bool dfs(int u)
{
    inq[u] = true;
    for(int i=g.V[u].head;~i;i=g.E[i].next)
    {
        int v = g.E[i].v;
        double w = g.E[i].w;
        if(d[u] + w > d[v])
        {
            d[v] = d[u] + w;
            if(inq[v] || dfs(v))
                return true;
        }
    }
    inq[u] = false;
    return false;
}

bool hasCircle(int n)
{
    memset(inq,false,sizeof(inq));
    memset(d,0,sizeof(d));
    for(int i=0;i<=n;i++)
        if(dfs(i))
            return true;
    return false;
}

int main()
{
    int n,m,l,u;
    while(~scanf("%d%d%d%d",&n,&m,&l,&u))
    {
        g.init();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int x;
                scanf("%d",&x);
                g.add_edge(n+j,i,log(1.0*l/x));
                g.add_edge(i,n+j,log(1.0*x/u));
            }
        for(int i=1;i<=n+m;i++)
            g.add_edge(0,i,0);
        puts(hasCircle(n+m)?"NO":"YES");
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: