zoukankan      html  css  js  c++  java
  • poj 3680 Intervals(费用流)

    http://poj.org/problem?id=3680

    巧妙的构图。

    题目:给定N个区间(ai,bi)权值wi,求最大权和且每个点最多覆盖K次。

    构图:将区间端点离散化,将第i个点连第i+1个点花费为0,容量为INF,即addedge(i,i+1,0,INF)(可用来跳过一些区间);

       再处理N个区间(ai,bi),addedge(ai,bi,-wi,1);

       最后源点连第一个点,addedge(src,1,0,k);最后一个点连汇点,addedge(n,sink,0,k)。

    原理:构完图之后做最小费用最大流,其实就是找不大于K条增广路。如果两个区间有交集,则不能一次流过,要分成两条增广路流过;反之,则可一次流过。

      1 /*
      2  *Author:       Zhaofa Fang
      3  *Created time: 2013-07-19-10.41
      4  *Language:     C++
      5  */
      6 #include <cstdio>
      7 #include <cstdlib>
      8 #include <sstream>
      9 #include <iostream>
     10 #include <cmath>
     11 #include <cstring>
     12 #include <algorithm>
     13 #include <string>
     14 #include <utility>
     15 #include <vector>
     16 #include <queue>
     17 #include <map>
     18 #include <set>
     19 using namespace std;
     20 
     21 typedef long long ll;
     22 typedef pair<int,int> PII;
     23 #define DEBUG(x) cout<< #x << ':' << x << endl
     24 #define FOR(i,s,t) for(int i = (s);i <= (t);i++)
     25 #define FORD(i,s,t) for(int i = (s);i >= (t);i--)
     26 #define REP(i,n) for(int i=0;i<(n);i++)
     27 #define REPD(i,n) for(int i=(n-1);i>=0;i--)
     28 #define PII pair<int,int>
     29 #define PB push_back
     30 #define MP make_pair
     31 #define ft first
     32 #define sd second
     33 #define lowbit(x) (x&(-x))
     34 #define INF (1<<30)
     35 #define eps (1e-8)
     36 
     37 const int maxm = 5000;
     38 const int maxn = 405;
     39 int ans,anscost;
     40 struct Edge {
     41     int u,v,cost,cap,flow,next;
     42 }et[maxm];
     43 int S,T;
     44 int eh[maxn],tot,low[maxn],p[maxn],dist[maxn];
     45 bool vist[maxn];
     46 bool spfa(){
     47     queue<int>que;
     48     memset(vist,0,sizeof(vist));
     49     memset(p,-1,sizeof(p));
     50     fill(dist,dist+maxn,INF);
     51     vist[S] = 1,low[S] = INF,dist[S] = 0;
     52     que.push(S);
     53     while(!que.empty()){
     54         int u = que.front();
     55         que.pop();
     56         vist[u] = false;
     57         for(int i=eh[u];i!=-1;i=et[i].next){
     58             int v = et[i].v,cost = et[i].cost,cap=et[i].cap,flow=et[i].flow;
     59             if(flow < cap && dist[u] + cost < dist[v]){
     60                 dist[v] = dist[u] + cost;
     61                 p[v] = i;
     62                 low[v] = min(low[u],cap-flow);
     63                 if(!vist[v]){
     64                     vist[v] = 1;
     65                     que.push(v);
     66                 }
     67             }
     68         }
     69     }
     70     return dist[T]!=INF;
     71 }
     72 void costflow(){
     73     ans = 0,anscost = 0;
     74     int num=0;
     75     while(spfa()){
     76         int x = p[T];
     77         ans += low[T];
     78         anscost += low[T]*dist[T];
     79         while(x!=-1){
     80             et[x].flow += low[T];
     81             et[x^1].flow -= low[T];
     82             et[x^1].cost = -et[x].cost;
     83             x = p[et[x].u];
     84         }
     85     }
     86 }
     87 void add(int u,int v,int cost,int cap,int flow){
     88     Edge e = {u,v,cost,cap,flow,eh[u]};
     89     et[tot] = e;
     90     eh[u] = tot ++;
     91 }
     92 void addedge(int u,int v,int cost,int cap){
     93     add(u,v,cost,cap,0);add(v,u,-cost,0,0);
     94 }
     95 void init(){
     96     tot = 0;
     97     memset(eh,-1,sizeof(eh));
     98 }
     99 int X[maxn];
    100 int a[maxn],b[maxn],w[maxn];
    101 int find(int key,int n){
    102     int r = lower_bound(X,X+n,key)-X;
    103     return r+1;
    104 }
    105 int main(){
    106     //freopen("in","r",stdin);
    107     //freopen("out","w",stdout);
    108     int Ca;
    109     scanf("%d",&Ca);
    110     while(Ca--){
    111         int N,K;
    112         scanf("%d%d",&N,&K);
    113         int cnt = 0;
    114         init();
    115         REP(i,N){
    116             scanf("%d%d%d",&a[i],&b[i],&w[i]);
    117             X[cnt++]=a[i];X[cnt++]=b[i];
    118             w[i] = -w[i];
    119         }
    120         sort(X,X+cnt);
    121         int n = 1;
    122         FOR(i,1,cnt-1){
    123             if(X[i]!=X[i-1])X[n++]=X[i];
    124         }
    125         REP(i,n-1){
    126             addedge(i+1,i+2,0,INF);
    127         }
    128         REP(i,N){
    129             int l = find(a[i],n);
    130             int r = find(b[i],n);
    131             addedge(l,r,w[i],1);
    132         }
    133         addedge(0,1,0,K);
    134         addedge(n,n+1,0,K);
    135         S = 0;T = n+1;costflow();
    136         printf("%d
    ",-anscost);
    137 
    138     }
    139     return 0;
    140 }
    1300+MS
  • 相关阅读:
    Android 按键消息处理Android 按键消息处理
    objcopy
    SQLite多线程读写实践及常见问题总结
    android动画坐标定义
    Android动画效果translate、scale、alpha、rotate
    Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
    Flatten Binary Tree to Linked List
    Distinct Subsequences
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/fzf123/p/3200711.html
Copyright © 2011-2022 走看看