码迷,mamicode.com
首页 > 其他好文 > 详细

P3358 最长k可重区间集问题

时间:2020-01-29 21:51:46      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:bsp   class   ble   href   str   add   algo   info   set   

https://www.luogu.com.cn/problem/P3358

技术图片

最大费用最大流,建模方法:

黑线、紫线都是流量k,费用0,保障图的连通性,以及只能走k次

红线代表一个给定的区间,流量1代表只能取一次,费用为区间长度代表走过这条区间,可以获得区间长度的价值

 

跑最大费用最大流(开始时把边权取反,跑最小费用最大流,然后再取反)

需要离散化~

  1 #include<iostream>
  2 #include<cstring>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 struct edge{
  7     long long v,w,cost,fail;
  8     edge(){
  9     }
 10     edge(long long a,long long b,long long c,long long d){
 11         v=a;
 12         w=b;
 13         cost=c;
 14         fail=d;
 15     }
 16 }e[200100];
 17 long long n,k,s,t,m,incf[200100],pre[200100],vis[200100],dis[200100],head[200100],len,last[200100];
 18 long long Left[200100],Right[200010],u[200100],cnt,U[200100],val[200100];
 19 void add(long long x,long long y,long long z,long long c){
 20     e[len]=edge(y,z,c,head[x]);
 21     head[x]=len++;
 22     e[len]=edge(x,0,-c,head[y]);
 23     head[y]=len++;
 24 }
 25 bool spfa(){
 26     queue<long long> q;
 27     memset(vis,0,sizeof(vis));
 28     memset(dis,0x3f,sizeof(dis)); 
 29     q.push(s);
 30     dis[s]=0;
 31     vis[s]=1;
 32     incf[s]=(long long)1e17;
 33     while(!q.empty()){
 34 //        cout<<q.front()<<endl;
 35         long long now=q.front();
 36         vis[now]=0;
 37         q.pop();
 38         for(long long i=head[now];~i;i=e[i].fail){
 39         //    cout<<i<<endl;
 40             if(!e[i].w)continue;
 41             if(dis[e[i].v]>dis[now]+e[i].cost){
 42                 dis[e[i].v]=dis[now]+e[i].cost;
 43                 incf[e[i].v]=min(incf[now],e[i].w);
 44                 pre[e[i].v]=i;
 45                 last[e[i].v]=now;
 46             //    cout<<"pre of"<<e[i].v<<" is"<<now<<endl;
 47                 if(vis[e[i].v]==0){
 48                     vis[e[i].v]=1;
 49                     q.push(e[i].v);
 50                 }
 51             }
 52         } 
 53     }
 54     //cout<<1<<endl;
 55     if(dis[t]>=(long long)(1e17))return 0;
 56     else return 1;
 57 }
 58 long long maxflow=0;
 59 long long ans=0;
 60 long long inf=(long long)1e17;
 61 void update(){
 62     //cout<<"--------------------------"<<endl;
 63     long long now=t;
 64     while(now!=s){
 65     //    cout<<now<<" "<<last[now]<<endl;
 66         long long i=pre[now];
 67         e[i].w-=incf[t];
 68         e[i^1].w+=incf[t];
 69         now=last[now];
 70     } 
 71     maxflow+=incf[t];
 72     ans+=dis[t]*incf[t];
 73     //cout<<ans<<endl;
 74 //    cout<<ans<<endl;
 75 }   
 76 int main(){
 77     cin>>n>>k;
 78     memset(head,-1,sizeof(head)); 
 79     for(int i=1;i<=n;i++){
 80         cin>>Left[i]>>Right[i];
 81         u[++cnt]=Left[i];
 82         u[++cnt]=Right[i];
 83         val[i]=Right[i]-Left[i];
 84     }
 85     sort(u+1,u+cnt+1);
 86     int cnt1=0;
 87     for(int i=1;i<=cnt;i++){
 88         if(u[i]!=u[i-1]){
 89             U[++cnt1]=u[i];
 90         }
 91     }
 92     for(int i=1;i<=n;i++){
 93         for(int j=1;j<=cnt1;j++){
 94             if(Left[i]==U[j])Left[i]=j;
 95             if(Right[i]==U[j])Right[i]=j;
 96         }
 97     }
 98     long long Max=0;
 99     for(int i=1;i<=n;i++){
100         Max=max(Max,Right[i]);
101         add(Left[i],Right[i],1,-val[i]);
102     }
103     n=Max;
104     s=0;
105     t=Max+1;
106     for(int i=1;i<n;i++){
107         add(i,i+1,k,0);
108     }
109     add(s,1,k,0);
110     add(n,t,k,0);
111     while(spfa())update();
112     cout<<-ans<<endl;
113 }

 

P3358 最长k可重区间集问题

标签:bsp   class   ble   href   str   add   algo   info   set   

原文地址:https://www.cnblogs.com/wo-bu-yao-bao-ling/p/12241129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!