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
  • 相关阅读:
    文件操作2
    操作文件1
    标准库(一):collections之orderedDict
    类的模板导入
    类的继承
    类内成员和方法的使用
    redis高可用
    oracle数据库优化
    如何捕获oracle数据库异常
    oracle之语句触发器创建
  • 原文地址:https://www.cnblogs.com/fzf123/p/3200711.html
Copyright © 2011-2022 走看看