【POJ】【3680】Intervals

网络流/费用流


  引用下题解:

lyd:

首先把区间端点离散化,设原来的数值i离散化后的标号是c[i]。这样离散化之后,整个数轴被分成了一段段小区间。

1.建立S和T,从S到离散化后的第一个点连容量K,费用0的边。离散化后的最后一个点到T连容量K、费用0的边。

2.离散化后的相邻点之间(从i到i+1)连容量为K,费用为0的边。

3.输入的区间从离散化后的左端点到右端点连容量1、费用W的边。

  感觉好神啊……

其实应该只要把源点到第一个点的流量限制为k应该就可以了……这个构思蛮巧妙的……限制了每个地方最多有k个流出去。

另外,这题是最大费用最大流,所以按上面的建图方式需要改一下预处理和增广的条件,或者就是建图的时候所有的费用取负,再将最后答案取负。

  1 Source Code
  2 Problem: 3680        User: sdfzyhy
  3 Memory: 752K        Time: 563MS
  4 Language: G++        Result: Accepted
  5 
  6     Source Code
  7 
  8     //BZOJ 3680
  9     #include<cmath>
 10     #include<vector>
 11     #include<cstdio>
 12     #include<cstring>
 13     #include<cstdlib>
 14     #include<iostream>
 15     #include<algorithm>
 16     #define rep(i,n) for(int i=0;i<n;++i)
 17     #define F(i,j,n) for(int i=j;i<=n;++i)
 18     #define D(i,j,n) for(int i=j;i>=n;--i)
 19     #define pb push_back
 20     #define CC(a,b) memset(a,b,sizeof(a))
 21     using namespace std;
 22     int getint(){
 23         int v=0,sign=1; char ch=getchar();
 24         while(!isdigit(ch)) {if(ch=='-') sign=-1; ch=getchar();}
 25         while(isdigit(ch))  {v=v*10+ch-'0'; ch=getchar();}
 26         return v*sign;
 27     }
 28     const int N=510,M=100000,INF=~0u>>2;
 29     const double eps=1e-8;
 30     /*******************template********************/
 31     int n,m,k,ans,a[N],b[N],c[N],w[N];
 32     struct edge{int from,to,v,c;};
 33     struct Net{
 34         edge E[M];
 35         int head[N],next[M],cnt;
 36         void ins(int x,int y,int z,int c){
 37             E[++cnt]=(edge){x,y,z,c};
 38             next[cnt]=head[x]; head[x]=cnt;
 39         }
 40         void add(int x,int y,int z,int c){
 41             ins(x,y,z,c); ins(y,x,0,-c);
 42         }
 43         int S,T,d[N],Q[M],from[N];
 44         bool inq[N];
 45         bool spfa(){
 46             int l=0,r=-1;
 47             F(i,S,T) d[i]=INF;
 48             d[S]=0; Q[++r]=S; inq[S]=1;
 49             while(l<=r){
 50                 int x=Q[l++]; inq[x]=0;
 51                 for(int i=head[x];i;i=next[i])
 52                     if(E[i].v && d[x]+E[i].c<d[E[i].to]){
 53                         d[E[i].to]=d[x]+E[i].c;
 54                         from[E[i].to]=i;
 55                         if (!inq[E[i].to]){
 56                             Q[++r]=E[i].to;
 57                             inq[E[i].to]=1;
 58                         }
 59                     }
 60             }
 61             return d[T]!=INF;
 62         }
 63         void mcf(){
 64             int x=INF;
 65             for(int i=from[T];i;i=from[E[i].from])
 66                 x=min(x,E[i].v);
 67             for(int i=from[T];i;i=from[E[i].from]){
 68                 E[i].v-=x;
 69                 E[i^1].v+=x;
 70             }
 71             ans+=x*d[T];
 72         }
 73         void init(){
 74             n=getint(); k=getint();
 75             cnt=1; ans=0;
 76             memset(head,0,sizeof head);
 77             int x,y;
 78             F(i,1,n){
 79                 a[i]=c[(i<<1)-1]=getint();
 80                 b[i]=c[i<<1]=getint();
 81                 w[i]=getint();
 82             }
 83             sort(c+1,c+n*2+1);
 84             int num=unique(c+1,c+n*2+1)-c-1;
 85             S=0; T=num+1;
 86             F(i,0,num) add(i,i+1,k,0);
 87             F(i,1,n){
 88                 a[i]=lower_bound(c+1,c+num+1,a[i])-c;
 89                 b[i]=lower_bound(c+1,c+num+1,b[i])-c;
 90                 add(a[i],b[i],1,-w[i]);
 91             }
 92             while(spfa()) mcf();
 93             printf("%d
",-ans);
 94         }        
 95     }G1;
 96     int main(){
 97     #ifndef ONLINE_JUDGE
 98         freopen("input.txt","r",stdin);
 99     //    freopen("output.txt","w",stdout);
100     #endif
101         int T=getint();
102         while(T--) G1.init();
103         return 0;
104     }
View Code
Intervals
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 6880   Accepted: 2859

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 covered more than k times.

Input

The first line of input is the number of test case.
The first line of each test case contains two integers, N and K (1 ≤ KN ≤ 200).
The next N line each contain three integers ai, bi, wi(1 ≤ ai < bi ≤ 100,000, 1 ≤ wi ≤ 100,000) describing the intervals.
There is a blank line before each test case.

Output

For each test case output the maximum total weights in a separate line.

Sample Input

4

3 1
1 2 2
2 3 4
3 4 8

3 1
1 3 2
2 3 4
3 4 8

3 1
1 100000 100000
1 2 3
100 200 300

3 2
1 100000 100000
1 150 301
100 200 300

Sample Output

14
12
100000
100301

Source

[Submit]   [Go Back]   [Status]   [Discuss]

原文地址:https://www.cnblogs.com/Tunix/p/4349410.html