zoukankan      html  css  js  c++  java
  • POJ1201 Intervals

    题目的大意是给定若干(a,b,c)表示[a,b]之间有c个1,序列只能是0或者1,最后问在这些约束下,序列的最小长度。稍微变形就成了典型的差分约束问题,转化成S(b)-S(a)<=c这样的问题,然后用算导上的建模过程,a->b连条边,权值为c,因为这样的话,对于最后的dis(a)和dis(b),需要符合dis(b)<=dis(a)+w(a->b),也就是dis(b)-dis(a)<=w(a->b)。所以在加个虚拟的约束点后,点集v={v0,v1...vn}的解就是dis(0),dis(1)...dis(n){dis(i)表示建图后v0到vi的最短路},根据上述就能推出所对应的约束条件了。而这题就是求S(max)-S(min)的最小值,就是求Vmax到Vmin的最短距离,需要注意的是还有这样的约束条件0<=S(i+1)-S(i)<=1,这样同时也保证了图的连通性。对于POJ1364 King这题,是类似的,不过题目只给出"<"或者">",要转换,同时为保证连通性,可以这样处理,先将这n个点push到队列中,但这只算了虚节点的入队次数,但不管这些,入队n次以上,肯定是有负环的,可以反证。不过我后来加了个-1000<=S(i+1)-S(i)<=1000,这样一个条件,也AC,想法就是保证了它的连通性。

    感谢:

    http://www.cppblog.com/initiate/archive/2010/04/03/111530.html
    http://blog.csdn.net/ChinaCzy/archive/2010/07/26/5767025.aspx

    代码
    #include <iostream>
    #include
    <vector>
    #include
    <queue>
    using namespace std;

    const int MAX = 50005;

    struct NODE
    {
    int v, w;
    NODE() {}
    NODE(
    int vv, int ww) : v(vv), w(ww) {}
    };

    vector
    <vector<NODE> > mm;

    int in[MAX];
    int dis[MAX];

    int spfa(int beg, int end)
    {
    memset(
    in, 0, sizeof(in));
    memset(dis,
    -1, sizeof(dis));
    queue
    <int> Q;
    in[beg] = 1;
    dis[beg]
    = 0;
    Q.push(beg);
    while(!Q.empty())
    {
    int u = Q.front();
    Q.pop();
    in[u] = 0;
    for(int i = 0; i < mm[u].size(); i++)
    {
    int v = mm[u][i].v;
    int w = mm[u][i].w;
    if(dis[u] + w > dis[v])
    {
    dis[v]
    = dis[u] + w;
    if(in[v] == 0) Q.push(v), in[v] = 1;
    }
    }
    }
    return dis[end];
    }

    int main()
    {
    int cnt;
    mm.clear();
    mm.resize(MAX);
    scanf(
    "%d", &cnt);
    int minv = MAX, maxv = -1;
    while(cnt--)
    {
    int a, b, c;
    scanf(
    "%d%d%d", &a, &b, &c);
    b
    ++;
    minv
    = min(minv, a);
    maxv
    = max(maxv, b);
    //s(b) - s(a) >= c
    mm[b].push_back(NODE(a, c));
    }
    //0 <= s(i + 1) - s(i) <= 1

    for(int i = minv; i <= maxv - 1; i++)
    {
    mm[i
    + 1].push_back(NODE(i, 0));
    mm[i].push_back(NODE(i
    + 1, -1));
    }

    //必有解,无需判负环
    printf("%d\n", spfa(maxv, minv));
    }
  • 相关阅读:
    在mysql中计算百分比
    给指定的div增加滚动条
    Java高效编程之三【类和接口】
    Linux(CentOS) 如何查看当前占用CPU或内存最多的K个进程
    MapReduce:详解Shuffle过程
    Java高效编程之二【对所有对象都通用的方法】
    Java高效编程之一【创建和销毁对象】
    ANT命令总结(转载)
    linux 压缩文件的命令总结
    Cloudera CDH 、Impala本地通过Parcel安装配置详解
  • 原文地址:https://www.cnblogs.com/litstrong/p/1795268.html
Copyright © 2011-2022 走看看