poj3680 区间图的最大权独立集问题

  附上题目链接:http://poj.org/problem?id=3680

  题意大概是这样, 给你n个开区间, 每个开区间有一些权重, 现在从这些开区间里面选择一些区间, 使得每个点不被覆盖超过k次, 问你所能得到的最大权重是多少? 题目分析见挑战p247, 这里我们附上另一份题解:

  1. /*
  2. 都说这题是构图很巧的好题~我也赞一个吧,虽然我没有想到。
  3. 说说我的思考过程吧。
  4. 做这题是因为这题在网络流的分类里面,自然一开始就想构图了~
  5. (1)能作为结点的东西的只有两个,区间和端点,区间没什么道理,以端点做结点的话,离散化是要的;
  6. (2)k限制流量用,段的权值与流量没什么关系,是一种费用性的东西,所以是费用流;
  7. (3)考虑到区间包含连续的点,我画了一个S->1->2->...->T的线图(流量限制为k,费用暂时为0),并尝试对区间(a,b)(权值为w)加边add(S,a,w,1)和add(b,T,w,1),但又捣乱了流量关系,于是继续凌乱中~
  8. 在哪个路口乱了咧?没理清楚的流量关系~差一点了!
  9. 建图改成代码中的那样后,即add(S,1,0,k),add(cnt,T,0,k),add(i,i+1,0,k),add(a,b,-w,1),a到b的流量一旦形成,a和b之间的点因为在a点之后,流量自然会超限,b之后的点流量也不会受影响,太可爱了!如果这个完整的思考过程属于我就爽了  代码如下:
  10. #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 450;
    
    struct Edge { int from, to, cap, flow, cost; };
    vector<Edge> edges;
    vector<int> G[maxn];
    int inque[maxn];   //spfa
    int d[maxn];    //源点到当前点的最短路
    int p[maxn];    //入弧编号
    int a[maxn];    //可改进量
    
    void init(int n)
    {
        for(int i=0; i<=n; i++) G[i].clear();
        edges.clear();
    }
    
    void add_edge(int from, int to, int cap, int cost)
    {
        edges.push_back((Edge){from, to, cap, 0, cost});
        edges.push_back((Edge){to, from, 0, 0, -cost});
        int m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    
    bool spfa(int s, int t, int &flow, long long &cost)
    {
        memset(d, 0x3f, sizeof(d));
        memset(inque, 0, sizeof(inque));
        d[s] = 0; inque[s] = 1;
        a[s] = inf; p[s] = 0;
        queue<int> que;
        que.push(s);
        while(!que.empty()){
            int u = que.front(); que.pop();
            inque[u] = 0;
            for(int i=0; i<G[u].size(); i++){
                Edge e = edges[G[u][i]];
                if(e.cap>e.flow && d[e.to]>d[u]+e.cost){
                    d[e.to] = d[u] + e.cost;
                    if(!inque[e.to]) que.push(e.to), inque[e.to]=1;
                    p[e.to] = G[u][i];   //e.to的入弧编号
                    a[e.to] = min(a[u], e.cap-e.flow);   //更新可改进量
                }
            }
        }
        if(d[t] == inf) return false;
        flow += a[t];
        cost += (long long)a[t]*(long long)d[t];
        for(int u=t; u!=s; u=edges[p[u]].from){
            edges[p[u]].flow += a[t];
            edges[p[u]^1].flow -= a[t];
        }
        return true;
    }
    
    int MCMF(int s, int t, long long &cost)
    {
        int flow = 0; cost = 0;
        while(spfa(s, t, flow, cost));
        return flow;
    }
    
    int aa[250], bb[250], ww[250];
    vector<int> x;
    
    int main() {
        int T;
        scanf("%d", &T);
        while(T--) {
            int N, K;
            scanf("%d%d", &N, &K);
            x.clear();
            for(int i=0; i<N; i++) {
                int a, b, w;
                scanf("%d%d%d", &a, &b, &w);
                x.push_back(a);
                x.push_back(b);
                aa[i] = a;
                bb[i] = b;
                ww[i] = w;
            }
            sort(x.begin(), x.end());
            x.erase(unique(x.begin(), x.end()), x.end());
            //debug
            //for(int i=0; i<x.size(); i++)
            //    cout<<x[i]<<‘ ‘;
            //cout<<endl;
            int m = x.size();
            int s = m, t = m+1;
            init(m+1);
            add_edge(s, 0, K, 0);
            add_edge(m-1, t, K, 0);
            for(int i=0; i+1<x.size(); i++) {
                add_edge(i, i+1, K, 0);
            }
            for(int i=0; i<N; i++) {
                int u = find(x.begin(), x.end(), aa[i]) - x.begin();
                int v = find(x.begin(), x.end(), bb[i]) - x.begin();
                add_edge(u, v, 1, -ww[i]);
            }
            long long cost = 0;
            MCMF(s, t, cost);
            cout<<-cost<<endl;
        }
        return 0;
    }
时间: 2024-10-14 18:49:54

poj3680 区间图的最大权独立集问题的相关文章

二分图最小点权覆盖 二分图最大权独立集 方格取数 最小割

二分图最小点权覆盖: 每一条边 (u, v) 都是一个限制条件, 要求 u 和 v 不能同时取得. 我们考虑先取得所有的, 然后减去最小的点权. 建立原点 S , 连向二分图左边的所有点, 与 S 连通的意义是左边的点被选择了, 或者右边的点没有被选择. 建立汇点 T , 二分图右边的所有点连向它, 与 T 连通的意义是左边的点没有被选择, 或者右边的点被选择了. 利用最小割最大流定理, 我们跑最大流, 再根据最后一次 BFS 得出的情报构造方案. 定理 覆盖集与独立集互补. 证明 即证明覆盖集

解题报告 之 POJ3680 Intervals

解题报告 之 POJ3680 Intervals Description You are given N weighted open intervals. The ith interval covers (ai, bi) and weighs wi. Your task is to pick some of the intervals to maximize the total weights under the limit that no point in the real axis is c

HDU 1565:方格取数(1)(最大点权独立集)***

http://acm.hdu.edu.cn/showproblem.php?pid=1565 题意:中文. 思路:一个棋盘,要使得相邻的点不能同时选,问最大和是多少,这个问题就是最大点权独立集. 可以转化为所有的点权 - 最小点权覆盖集(最小割) = 最大点权独立集. 转载两个的定义:这里. 覆盖集(vertex covering set,VCS)是无向图的一个点集,使得该图中所有边都至少有一个端点在该集合内.形式化的定义是点覆盖集为G'VV∈(,)uvE∀∈,满足对于,都有 或成立,即,'uV

LightOJ1360 Skyscraper(DP)

题目大概是,一个数轴上n个线段,每个线段都有起始坐标.长度和权值,问从中取出没有公共交点的线段的最大权和. 取k次是个经典的最小费用最大流问题,不过这题建容量网络有20W个点,离散化最多也要6W个点,跑不动最小费用最大流的样子.. 其实这题也是个经典的DP,区间图最大权独立集问题,<挑战程序设计竞赛>有介绍. dp[i]表示坐标在[0,i]范围内能得到的最大的线段权值和 dp[i]=max(dp[i-1],max(dp[j]+w)([j,i]是一条权w的线段)) 用左闭右开的区间表示这道题的线

BZOJ 1040: [ZJOI2008]骑士 [DP 环套树]

传送门 题意:环套树的最大权独立集 一开始想处理出外向树树形$DP$然后找到环再做个环形$DP$ 然后看了看别人的题解其实只要断开环做两遍树形$DP$就行了...有道理! 然后洛谷时限再次不科学,卡常失败$SAD$ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; co

一些简单的网络流模型

一.最大权闭合图 对于一个图(V, E)由点集V和一些有向边集E组成,每个点有一定权值,对于一个合法子集,若有一条有向边(u,v)并且u在子集中,则v也必须在子集中,求子集中所有元素权值和最大的子集 分析:考虑每个点有两种状况,选和不选,所以考虑最小割,但是要求最大费用: 先假设取了所有正权点,从原点向所有正权点连边,从所有负权点向汇点连边,容量为权值的绝对值, 对于一个割[S,T](S内的点表示选择了的点), 正权点在S内,表示选了这个点,与S相连的边没有被割,若在T内,表示这个点被割则被割,

BZOJ3548 : [ONTAK2010]Party

首先将朋友通过并查集缩起来,因为$P\geq\frac{n(n-1)}{3}$,所以最后最多剩下$46$个点. 将自相矛盾的点删掉,就变成求最大权独立集问题,这等于求补图的最大团. 然后直接用Bron-Kerbosch算法枚举所有极大团,枚举的时候更新答案即可. 时间复杂度$O(3^\frac{n}{3})$. #include<cstdio> #define N 46 typedef unsigned long long ll; int n,m,q,i,j,x,y,ans,sum,flag,

【BZOJ 3144】 3144: [Hnoi2013]切糕 (最小割模型)

3144: [Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1764  Solved: 965 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R). 100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超

最小割 总结&amp;&amp;做题记录

模型要点: 1.一般适用于二取一问题或者01规划. 2.利用最小割=最大流,转化为最大流求之. 建议阅读胡伯涛的论文 <<最小割模型在信息学竞赛的应用>>,有精彩有序的证明和各种模型. 相关题目: 1.太空飞行计划(网络流24题) 题目大意: 有一些实验和仪器,做每个实验有相应的报酬,但是需要买好相应的仪器(多个实验可以共用),仪器需要相应的钱.求最大利润. 题解: 经典的最大权闭合图模型.闭合图的概念是原图的一个点集,要求该点集的所有出边仍指向该点集合,最大权闭合图就是给每个点加