zoukankan      html  css  js  c++  java
  • bzoj2257[POI2011]Programming Contest

    首先可以费用流建图,左边一堆点表示人,右边一堆点表示题,源点向每个人连floor(t/r)条边,费用依次为r,2r,3r….然后写了一个卡不过去,动态加边也卡不过去,然后我想:这里一定有一些不为人知的卡常黑科技!然后去查题解发现不是费用流…因为只有源点向人的连边有费用,那么费用流的过程其实是:考虑让尽量多的人做费用为r的第一道题,然后让尽量多的人做费用为2r的第二道题…然后我们发现,写一个动态加边的dinic就可以了…我这里没有加边,直接把源点向人连边的边权重置,效果是一样的.

    边权重置之后就不能沿着反向边反悔了,但这道题的性质使得不考虑反悔的情况也是对的.如果考虑费用为r的时候让1号人做了1号题,然后考虑费用为2r的时候发现可以让2号人做1号题,1号人做2号题,这种情况是不会出现的,因为在考虑费用为r的时候就可以让2号人做1号题,1号人做2号题.

    一开始跑费用流T了好几发,然后dinic当前弧优化写残了又T了好几发...

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1005,maxm=1000005;
    struct edge{
      int to,next,w;
    }lst[maxm];int len=0,first[maxn],_first[maxn];
    void addedge(int a,int b,int w){
      lst[len].to=b;lst[len].next=first[a];lst[len].w=w;first[a]=len++;
      lst[len].to=a;lst[len].next=first[b];lst[len].w=0;first[b]=len++;
    }
    int q[maxn],dis[maxn],vis[maxn],s,t,head,tail,T;
    bool bfs(){
      head=tail=0;vis[s]=++T;dis[s]=0;q[tail++]=s;
      while(head!=tail){
        int x=q[head++];
        for(int pt=first[x];pt!=-1;pt=lst[pt].next){
          if(lst[pt].w&&vis[lst[pt].to]!=T){
        dis[lst[pt].to]=dis[x]+1;vis[lst[pt].to]=T;q[tail++]=lst[pt].to;
          }
        }
      }
      if(vis[t]==T)memcpy(_first,first,sizeof(first));
      return vis[t]==T;
    }
    int dfs(int x,int lim){
      if(x==t)return lim;
      int flow=0,a;
      for(int pt=_first[x];pt!=-1;pt=lst[pt].next){
        _first[x]=pt;
        if(lst[pt].w&&dis[lst[pt].to]==dis[x]+1&&(a=dfs(lst[pt].to,min(lst[pt].w,lim-flow)))){
          lst[pt].w-=a;lst[pt^1].w+=a;flow+=a;
          if(lim==flow)return lim;
        }
      }
      return flow;
    }
    int dinic(){
      int ans=0,x;
      while(bfs())while(x=dfs(s,0x7f7f7f7f))ans+=x;
      return ans;
    }
    int n,m,r,lim,k;
    int main(){
      memset(first,-1,sizeof(first));
      scanf("%d%d%d%d%d",&n,&m,&r,&lim,&k);
      s=0;t=n+m+1;
      for(int i=1;i<=m;++i)addedge(n+i,t,1);
      int a,b;
      for(int i=1;i<=k;++i){
        scanf("%d%d",&a,&b);
        addedge(a,n+b,1);
      }
      int ans1=0,ans2=0;
      for(int i=1;i<=n;++i)addedge(s,i,1);
      for(int j=1;j*r<=lim;++j){
        int tmp=dinic();ans1+=tmp;ans2+=tmp*j*r;
        if(tmp==0)break;
        for(int i=1;i<=n;++i){
          lst[len-i*2].w=1;lst[len-i*2+1].w=0; 
        }
      }
      printf("%d %d
    ",ans1,ans2);
      return 0;
    }
  • 相关阅读:
    使用 kill 命令杀死 java进程,你用对了吗?
    脚本 启动/停止 jar包服务
    Zipkin和微服务链路跟踪
    nacos初探--作为配置中心
    第一次有人把“分布式事务”讲的这么简单明了
    SquishIt引起的HTTP Error 500.0
    imagesLoaded – 检测网页中的图片是否加载
    25个精美的创意机构和设计工作室网站案例
    使用 FocusPoint.js 实现图片的响应式裁剪
    设计师收藏的20款英文手写字体【免费下载】
  • 原文地址:https://www.cnblogs.com/liu-runda/p/6396875.html
Copyright © 2011-2022 走看看