zoukankan      html  css  js  c++  java
  • POJ 3680

    一道思想比较神奇的网络流....

    题意:给定一些带权的左闭右开区间,求一种选择区间的方案满足每个点被覆盖不超过k次并使权值和最大。

    一开始的思路是将区间离散化后建立一个二分图模型,一边是点,一边是区间,然后把每个点和覆盖它的区间连边,但是这样是没法做的,因为区间的权值在点上,而且流量也没法弄

    我们考虑建立这样一个模型,将所有的点串连,然后对于一个区间(l,r],我们在点l和点r处连一条边,容量为1,费用为区间权值,对于相邻两点,我们连容量为INF,费用为0的边,然后S向1号点连边,容量为K,费用为0,n号点向T连边,容量为K,费用为0,跑一遍最大费用最大流即可。

    为什么这样是对的,我们考虑对于每次增广,一定是选了若干个互不相交的区间,而且这些区间一定和我们之前增广的区间有交,这样我们连续增广K次,每个点被覆盖一定不超过K次

    感觉自己网络流只会二分图建图....这方面还有待加强..

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 #define maxn 3005
      6 const int INF=1000000000;
      7 int pre[maxn],last[maxn],other[maxn],cap[maxn],cost[maxn];
      8 int que[maxn+4],dis[maxn],next[maxn];
      9 int C,n,m,k,b[maxn],l,S,T,ans;
     10 bool vis[maxn];
     11 struct Line
     12 {
     13     int l,r,w;
     14 }a[maxn];
     15 
     16 void init(void) 
     17 {
     18     memset(last,0,sizeof last);
     19     n=0;ans=0;l=1;
     20     scanf("%d%d",&m,&k);
     21     for (int i=1;i<=m;i++) 
     22     {
     23         scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].w);
     24         b[++n]=a[i].l;
     25         b[++n]=a[i].r;
     26     }
     27     sort(b+1,b+n+1);
     28     n=unique(b+1,b+n+1)-b-1;
     29     for (int i=1;i<=m;i++) 
     30         a[i].l=lower_bound(b+1,b+n+1,a[i].l)-b,
     31         a[i].r=lower_bound(b+1,b+n+1,a[i].r)-b;
     32 }
     33 
     34 void connect(int x,int y,int z,int w)
     35 {
     36     l++;
     37     pre[l]=last[x];
     38     last[x]=l;
     39     other[l]=y;
     40     cap[l]=z;
     41     cost[l]=w;
     42     swap(x,y);
     43     l++;
     44     pre[l]=last[x];
     45     last[x]=l;
     46     other[l]=y;
     47     cap[l]=0;
     48     cost[l]=-w;
     49 }
     50 
     51 bool spfa(void) 
     52 {
     53     memset(dis,-1,sizeof dis);
     54     memset(next,0,sizeof next);
     55     que[1]=S;dis[S]=0;
     56     int h=0,t=1;
     57     while (h!=t) 
     58     {
     59         h=h%maxn+1;
     60         int u=que[h];vis[u]=0;
     61         for (int p=last[u];p;p=pre[p])
     62         {
     63             int v=other[p];
     64             if (cap[p]==0) continue;
     65             if (dis[v]<dis[u]+cost[p]) 
     66             {
     67                 dis[v]=dis[u]+cost[p];
     68                 next[v]=p;
     69                 if (vis[v]) continue;
     70                 t=t%maxn+1;
     71                 que[t]=v;
     72                 vis[v]=1;
     73             }
     74         }
     75     }
     76     return dis[T]>0;
     77 }
     78 
     79 void MCMF(void) 
     80 {
     81     while (spfa()) 
     82     {
     83         int flow=INF;
     84         for (int p=next[T];p;p=next[other[p^1]]) flow=min(flow,cap[p]);
     85         for (int p=next[T];p;p=next[other[p^1]]) 
     86             cap[p]-=flow,cap[p^1]+=flow;
     87         ans+=flow*dis[T];
     88     }
     89 }
     90 
     91 int main()
     92 {
     93     scanf("%d",&C);
     94     while (C--) 
     95     {
     96         init();
     97         for (int i=1;i<n;i++)
     98             connect(i,i+1,INF,0);
     99         S=n+1;T=n+2;
    100         connect(S,1,k,0);
    101         connect(n,T,k,0);
    102         for (int i=1;i<=m;i++) connect(a[i].l,a[i].r,1,a[i].w);
    103         MCMF();
    104         printf("%d\n",ans);
    105     }
    106     return 0;
    107 }
  • 相关阅读:
    Android教程 -07 Activity的任务栈和启动模式
    ViewPager封装工具类: 轻松实现APP导航或APP中的广告栏
    hdu 5900 区间dp
    状压dp入门
    poj 3280
    hdu 4745 two Rabits
    食了智,过来水一发
    poj 2142 the Balance
    hdu 6188 Duizi and Shunzi
    hdu 6186 CS Course
  • 原文地址:https://www.cnblogs.com/lvyouyw/p/6872277.html
Copyright © 2011-2022 走看看