zoukankan      html  css  js  c++  java
  • 「网络流 24 题」最长 k 可重区间集

    给定区间集合$I$和正整数$k$, 计算$I$的最长$k$可重区间集的长度.

    区间离散化到$[1,2n]$, $S$与$1$连边$(k,0)$, $i$与$i+1$连边$(k,0)$, $2n$与$T$连边$(k,0)$. 对于每个区间$(l,r)$, $l$与$r$连边$(1,l-r)$.

    最小费用相反数就为最大长度

    #include <iostream>
    #include <sstream>
    #include <algorithm>
    #include <cstdio>
    #include <math.h>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <string.h>
    #include <bitset>
    #include <unordered_map>
    #define REP(i,a,n) for(int i=a;i<=n;++i)
    #define PER(i,a,n) for(int i=n;i>=a;--i)
    #define hr putchar(10)
    #define pb push_back
    #define lc (o<<1)
    #define rc (lc|1)
    #define mid ((l+r)>>1)
    #define ls lc,l,mid
    #define rs rc,mid+1,r
    #define x first
    #define y second
    #define io std::ios::sync_with_stdio(false)
    #define endl '
    '
    #define DB(a) ({REP(__i,1,n) cout<<a[__i]<<' ';hr;})
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const int P = 1e9+7, P2 = 998244353, INF = 0x3f3f3f3f;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
    ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
    inline int rd() {int x=0;char p=getchar();while(p<'0'||p>'9')p=getchar();while(p>='0'&&p<='9')x=x*10+p-'0',p=getchar();return x;}
    //head
    
    
    #ifdef ONLINE_JUDGE
    const int N = 1e6+10;
    #else
    const int N = 999;
    #endif
    
    int n, m, k, S, T;
    struct _ {int from,to,w,f;};
    vector<_> E;
    vector<int> g[N];
    int a[N], pre[N], inq[N], d[N];
    int mf,mc;
    queue<int> q;
    void add(int x, int y, int c, int w) {
        g[x].pb(E.size());
        E.pb({x,y,c,w});
        g[y].pb(E.size());
        E.pb({y,x,0,-w});
    }
    void mfmc() {
    	mf=mc=0;
        while (1) {
            REP(i,1,T) a[i]=d[i]=INF,inq[i]=0;
            q.push(S),d[S]=0;
            while (!q.empty()) {
                int x=q.front(); q.pop();
                inq[x] = 0;
                for (auto t:g[x]) {
                    auto e=E[t];
                    if (e.w>0&&d[e.to]>d[x]+e.f) {
                        d[e.to]=d[x]+e.f;
                        pre[e.to]=t;
                        a[e.to]=min(a[x],e.w);
                        if (!inq[e.to]) {
                            inq[e.to]=1;
                            q.push(e.to);
                        }
                    }
                }
            }
            if (a[T]==INF) break;
            for (int u=T;u!=S;u=E[pre[u]].from) {
                E[pre[u]].w-=a[T];
                E[pre[u]^1].w+=a[T];
            }
            mf+=a[T],mc+=a[T]*d[T];
        }
    }
    
    
    int b[N], l[N], r[N];
    int main() {
    	scanf("%d%d", &n, &k);
    	REP(i,1,n) {
    		scanf("%d%d",l+i,r+i);
    		b[++*b]=l[i],b[++*b]=r[i];
    	}
    	sort(b+1,b+1+*b),*b=unique(b+1,b+1+*b)-b-1;
    	REP(i,1,n) {
    		l[i]=lower_bound(b+1,b+1+*b,l[i])-b;
    		r[i]=lower_bound(b+1,b+1+*b,r[i])-b;
    	}
    	S = *b+1, T = S+1;
    	add(S,1,k,0),add(*b,T,k,0);
    	REP(i,2,*b) add(i-1,i,k,0);
    	REP(i,1,n) add(l[i],r[i],1,-b[r[i]]+b[l[i]]);
    	mfmc();
    	printf("%d
    ", -mc);
    }
    
  • 相关阅读:
    Java实现 计蒜客 拯救行动
    Java实现 计蒜客 拯救行动
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 173 二叉搜索树迭代器
    Java实现 LeetCode 173 二叉搜索树迭代器
    Visual Studio的SDK配置
    怎样使用CMenu类
    mfc menu用法一
  • 原文地址:https://www.cnblogs.com/uid001/p/10990261.html
Copyright © 2011-2022 走看看