poj 1752 Advertisement (区间差分约束+最长路 输出可行解)


Advertisement
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 919 Accepted: 331 Special Judge

Description

The Department of Recreation has decided that it must be more profitable, and it wants to sell advertising space along a popular jogging path at a local park. They have built a number of billboards (special signs for advertisements) along the path and have decided to sell advertising space on these billboards. Billboards are situated evenly along the jogging path, and they are given consecutive integer numbers corresponding to their order along the path. At most one advertisement can be placed on each billboard. 

A particular client wishes to purchase advertising space on these billboards but needs guarantees that every jogger will see it's advertisement at least K times while running along the path. However, different joggers run along different parts of the path. 

Interviews with joggers revealed that each of them has chosen a section of the path which he/she likes to run along every day. Since advertisers care only about billboards seen by joggers, each jogger's personal path can be identified by the sequence of billboards viewed during a run. Taking into account that billboards are numbered consecutively, it is sufficient to record the first and the last billboard numbers seen by each jogger. 

Unfortunately, interviews with joggers also showed that some joggers don't run far enough to see K billboards. Some of them are in such bad shape that they get to see only one billboard (here, the first and last billboard numbers for their path will be identical). Since out-of-shape joggers won't get to see K billboards, the client requires that they see an advertisement on every billboard along their section of the path. Although this is not as good as them seeing K advertisements, this is the best that can be done and it's enough to satisfy the client. 

In order to reduce advertising costs, the client hires you to figure out how to minimize the number of billboards they need to pay for and, at the same time, satisfy stated requirements. 

Input

The first line of the input contains two integers K and N (1 <= K, N <= 1000) separated by a space. K is the minimal number of advertisements that every jogger must see, and N is the total number of joggers.

The following N lines describe the path of each jogger. Each line contains two integers Ai and Bi (both numbers are not greater than 10000 by absolute value). Ai represents the first billboard number seen by jogger number i and Bi gives the last billboard number seen by that jogger. During a run, jogger i will see billboards Ai, Bi and all billboards between them. 

Output

On the fist line of the output file, write a single integer M. This number gives the minimal number of advertisements that should be placed on billboards in order to fulfill the client's requirements. Then write M lines with one number on each line. These numbers give (in ascending order) the billboard numbers on which the client's advertisements should be placed.

Sample Input

5 10
1 10
20 27
0 -3
15 15
8 2
7 30
-1 -10
27 20
2 9
14 21

Sample Output

19
-5
-4
-3
-2
-1
0
4
5
6
7
8
15
18
19
20
21
25
26
27

Source


题目大意:题目大意:有n个人在一条路上跑步,广告商准备在这条路上设置广告牌,假设这条路上每一个点有一个广告牌 
现在已知这n个人从Ai开始跑,到Bi结束,那么他可以看到max(Ai,Bi)-min(Ai,Bi)+1的广告牌数,现在广告商 
需要每个人都要看到至少k个广告牌(如果区间长度不够K,那么需要看到区间长度),求需要设置的最少广告牌数以及一组合法解


思路:

常规区间差分约束, 这题让我意识到,最长路可以直接在spfa里 把 > 改成 < 号, 如果要变成最短路跑的话, 直接把权值取相反就好了, 构图跟原来一样的,仅仅改变权值

因为我们维护的是前缀和, 跑得是前缀和的最长路, 所以最后输出哪个广告牌存在时,得到dis[i]-dis[i-1]==1,即i-1到i有一块广告牌输出i,总的广告牌数存在在d[end],另外这题vector过不了- -

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10005;
const int INF = 1e9;
//struct node
//{
//    int to, w;
//    node(){}
//    node(int tt, int ww) : to(tt), w(ww){}
//};
//vector<node> v[maxn*2];
int book[maxn*3], cnt[maxn*3], dis[maxn*3],  head[maxn*4], n, k, K, x, y;
struct node
{
    int v, next, w;
}edge[maxn*4];

void addEdge(int u, int v, int w)
{
    edge[k].v = v;
    edge[k].w = w;
    edge[k].next = head[u];
    head[u] = k;
}
void spfa(int s, int e)
{
    memset(book, 0, sizeof(book));
    for(int i = 0; i < maxn*3; i++) dis[i] = INF;
    queue<int> q;
    q.push(s);
    book[s] = 1;
    dis[s] = 0;
    cnt[s] = 1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        book[u] = 0;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int to = edge[i].v;
            if(dis[u]+edge[i].w < dis[to])  //这里可以直接改成 > , 权值不用取负,那样初始值就是-inf
            {
                dis[to] = dis[u] + edge[i].w;
                if(!book[to])
                {
                    book[to] = 1;
                    q.push(to);
                }
            }
        }
    }
    printf("%d\n", -dis[e]);
     for(int i = s; i <= e; i++)  //输出可行解, 另外注意是 dis【i-1】-dis【i】, 因为权值取反了
        {
            if(dis[i-1]-dis[i] == 1)
                printf("%d\n", i-maxn);
        }
    return ;
}
int main()
{
    while(~scanf("%d%d", &K, &n))
    {
        memset(cnt, 0, sizeof(cnt));
        memset(dis, 0, sizeof(dis));
        memset(head, -1, sizeof(head));
        k = 0;
//        for(int i = 0; i < maxn*3; i++)
//            v[i].clear();
        int s = INF, e = -1;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d", &x, &y);
            x += maxn;
            y += maxn;
            if(x > y) swap(x, y);
            s = min(s, x-1);
            e = max(e, y);
//            v[x-1].push_back(node(y, -min(y-x+1, k)));
            addEdge(x-1, y, -min(y-x+1, K));
            k++;
        }
        for(int i = s; i <= e; i++)
        {
//            v[i+1].push_back(node(i, 1));
            addEdge(i+1, i, 1);
            k++;
            addEdge(i, i+1, 0);
            k++;
//            v[i].push_back(node(i+1, 0));
        }
        spfa(s, e);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值