[24 네트워크 흐름 문제 (3/24)] K 다시 긴 간격 설정 문제 (루오 밸리 P3358)

분석 :

이 비용 흐름의 매우 고전적인 모델입니다.

각 지점의 주제는 제한 할 수 있기 때문에 첫째, 우리는 선택 \ (케이 \)를 그 이유로 인해이 \ (케이 \) 시간 제한, 그래서 우리는 우리가 철거 소스하는 최대 유량으로 제한 될 수있다 두 지점에 \ (S_0 \)\ (S_1 \) 에서 \ (S_0 \) 포인트가 \ (S_1 \) 플로우 (K)에 접속 포인트를 선정 \ (0 \) 측. 크기의 대표까지 \ (케이 \) 사방 흐른다. 우리는 K에 묶여 있지만, 요구 사항은 최대 값이기 때문에, 우리가 요청하는 가장 큰 비용 최대 유량가되었습니다 말까지 최종 유량, 우리는 필요로이 값이 마이너스가 보장 할 수 있도록.

이 대부분있을 것 때문에 \ (N \) 의 범위에 \ (2N의 \) 점, 그래서 우리는 생각합니다 \ (2N의 \)를 분리 지적한다. 이산화 후, 이러한 이산 포스트 \ (2N 개의 \) 인접한 포인트 이산 점의 유속에 접속된다 \ (INF \) , 비용 (\ 0 \) 측 근방의 대표 요점은 서로에 도달 할 수 있습니다. 그럼 다시 전 (\ N-) \ 간격의 각 간격 \ ([L, R & LT] \) , 점 (\ L의 \) 와 점 \ (R & 중위 \) 에도 비용 사이 \ (- LR} {LEN_ \) , 흐름 \ (1 \) 는 다음 보낼 것입니다 선택하려면 현재의 간격을 나타내는 측면, \ (- 렌 {LR은} \ ) 모든 점 간격이 차지할뿐만 아니라 비용 (\를 1 \) 포인트 트래픽. 대신 좋은지도의 설립 후 후 최소의 비용을 복용 스트림의 최대 수를 할 수 있지만, 우리는 최소의 비용을 달렸다.

코드 :

// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define maxn 1006
#define maxm 10005
using namespace std;
int head[maxn],cnt=0;
int dis[maxn],vis[maxn],sp,ep,maxflow,cost;
int n,k;
const int INF=0x3f3f3f3f;
struct Node{
    int to,next,val,cost;
}q[maxm<<1];
int L[maxn],R[maxn];
vector<int>vec;
void init(){
    memset(head,-1, sizeof(head));
    cnt=2;
    maxflow=cost=0;
}
void addedge(int from,int to,int val,int cost){
    q[cnt].to=to;
    q[cnt].next=head[from];
    q[cnt].val=val;
    q[cnt].cost=cost;
    head[from]=cnt++;
}
void add_edge(int from,int to,int val,int cost){
    addedge(from,to,val,cost);
    addedge(to,from,0,-cost);
}
bool spfa(){
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    dis[sp]=0;
    vis[sp]=1;
    queue<int>que;
    que.push(sp);
    while(!que.empty()){
        int x=que.front();
        que.pop();
        vis[x]=0;
        for(int i=head[x];i!=-1;i=q[i].next){
            int to=q[i].to;
            if(dis[to]>dis[x]+q[i].cost&&q[i].val){
                dis[to]=dis[x]+q[i].cost;
                if(!vis[to]){
                    que.push(to);
                    vis[to]=1;
                }
            }
        }
    }
    return dis[ep]!=0x3f3f3f3f;
}
int dfs(int x,int flow){
    if(x==ep){
        vis[ep]=1;
        maxflow+=flow;
        return flow;
    }//可以到达t,加流
    int used=0;//该条路径可用流量
    vis[x]=1;
    for(int i=head[x];i!=-1;i=q[i].next){
        int to=q[i].to;
        if((vis[to]==0||to==ep)&&q[i].val!=0&&dis[to]==dis[x]+q[i].cost){
            int minflow=dfs(to,min(flow-used,q[i].val));
            if(minflow!=0){
                cost+=q[i].cost*minflow;
                q[i].val-=minflow;
                q[i^1].val+=minflow;
                used+=minflow;
            }
            //可以到达t,加费用,扣流量
            if(used==flow)break;
        }
    }
    return used;
}
int mincostmaxflow(){
    while(spfa()){
        vis[ep]=1;
        while(vis[ep]){
            memset(vis,0,sizeof(vis));
            dfs(sp,INF);
        }
    }
    return maxflow;
}
int main()
{
    scanf("%d%d",&n,&k);
    init();
    for(int i=1;i<=n;i++){
        scanf("%d%d",&L[i],&R[i]);
        if(L[i]>R[i]) swap(L[i],R[i]);
        vec.push_back(L[i]);
        vec.push_back(R[i]);
    }
    sort(vec.begin(),vec.end());
    int sz=vec.size();
    sp=sz+1,ep=sz+2;
    add_edge(sp,1,k,0);
    add_edge(sz,ep,k,0);
    for(int i=1;i<sz;i++) add_edge(i,i+1,k,0);
    for(int i=1;i<=n;i++){
        int l=lower_bound(vec.begin(),vec.end(),L[i])-vec.begin();
        int r=lower_bound(vec.begin(),vec.end(),R[i])-vec.begin();
        add_edge(l+1,r+1,1,vec[l]-vec[r]);
    }
    mincostmaxflow();
    printf("%d\n",-cost);
    return 0;
}

추천

출처www.cnblogs.com/Chen-Jr/p/11291378.html