poj3680 网络流离散化最大覆盖

他说每个点都不能被k个区间覆盖。

也就是说每个点最大流量为k,所以i-1到i的流量为k,费用为0.

我们在把输入数据的区间放进去,费用取负数。

源点指向1,n指向汇点,流量都为k。

如果有一个1-4的区间,我们选择了,之后1肯定被占用了1个流量,1一旦被占用了,代表着2,3都被占用了。

#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;

}




离散化方法:

          //两个端点放到一个容器中
            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());

     //取值,对于第i个,也就是aa[i],bb[i],ww[i]

           int u = find(x.begin(), x.end(), aa[i]) - x.begin();
           int v = find(x.begin(), x.end(), bb[i]) - x.begin();
     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值