zoukankan      html  css  js  c++  java
  • 【BZOJ】【3442】学习小组

    网络流/费用流


      orz zyf

      裸的费用流,根据题目描述即可建出如下的图:

      S->i 费用表示每有一个加入第 i 个小组的学生,需要花的钱,由于是跟流量(人数)的二次方相关,所以要拆边……然后每个人的报名费直接用支出减去即可(也就是每条边的费用都减去一个常量)

      i->j+m 根据矩阵连边……如果第 j 个学生能报名第 i 个小组即连一条边,费用为0。

      j+m->T 容量为k,费用为0,表示每个人最多报k个小组。

      但是这题很坑啊!限制条件是参与学生尽量多,也就是说在一定会亏的时候每人最多只报一个小组……刚刚的建图,最小费用最大流行不通了!

      我们想想,如果一个人报名了会使得总支出减少,那他肯定要报名某一个小组,如果不能减少的话……就让这个改变量为0好了!

      所以我们对于每个人 j ,连边S->j+m (k-1,0)表示这个人最多可以有k-1个报名机会直接放弃掉!(因为要让参与人数尽量多啊……所以不能是k)

      1 /**************************************************************
      2     Problem: 3442
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:1560 ms
      7     Memory:3624 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 3442
     11 #include<vector>
     12 #include<cstdio>
     13 #include<cstring>
     14 #include<cstdlib>
     15 #include<iostream>
     16 #include<algorithm>
     17 #define rep(i,n) for(int i=0;i<n;++i)
     18 #define F(i,j,n) for(int i=j;i<=n;++i)
     19 #define D(i,j,n) for(int i=j;i>=n;--i)
     20 #define pb push_back
     21 using namespace std;
     22 inline int getint(){
     23     int v=0,sign=1; char ch=getchar();
     24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     26     return v*sign;
     27 }
     28 const int N=410,M=100000,INF=~0u>>2;
     29 typedef long long LL;
     30 /******************tamplate*********************/
     31 int n,m,k,ans,tmp,num,c[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 from[N],Q[M],d[N],S,T,ed;
     44     bool inq[N],sign;
     45     bool spfa(){
     46         int l=0,r=-1;
     47         F(i,1,T) d[i]=INF;
     48         d[S]=0; Q[++r]=S; inq[S]=1;
     49         while(l<=r){
     50             int x=Q[l++];
     51             inq[x]=0;
     52             for(int i=head[x];i;i=next[i])
     53                 if(E[i].v>0 && d[x]+E[i].c<d[E[i].to]){
     54                     d[E[i].to]=d[x]+E[i].c;
     55                     from[E[i].to]=i;
     56                     if (!inq[E[i].to]){
     57                         Q[++r]=E[i].to;
     58                         inq[E[i].to]=1;
     59                     }
     60                 }
     61         }
     62         return d[T]!=INF;
     63     }
     64     void mcf(){
     65         int x=INF;
     66         for(int i=from[T];i;i=from[E[i].from])
     67             x=min(x,E[i].v);
     68         for(int i=from[T];i;i=from[E[i].from]){
     69             E[i].v-=x;
     70             E[i^1].v+=x;
     71         }
     72         ans+=x*d[T];
     73     }
     74     void init(){
     75         n=getint(); m=getint(); k=getint(); cnt=1;
     76         S=0; T=n+m+1; num=sign=0; tmp=-INF;
     77         F(i,1,m) c[i]=getint();
     78         int x;
     79         F(i,1,m){
     80             x=getint();
     81             F(j,1,n) add(S,i,1,c[i]*(j*2-1)-x);
     82         }
     83         char s[120];
     84         F(i,1,n) {
     85             scanf("%s",s+1);
     86             F(j,1,m){
     87                 x=s[j]-'0';
     88                 if (x) add(j,i+m,1,0);
     89             }
     90         }
     91         F(i,1,n) add(S,i+m,k-1,0),add(i+m,T,k,0);
     92         while(spfa()) mcf();
     93         printf("%d
    ",ans);
     94     }
     95 }G1;
     96  
     97 int main(){
     98 #ifndef ONLINE_JUDGE
     99     freopen("3442.in","r",stdin);
    100     freopen("3442.out","w",stdout);
    101 #endif
    102     G1.init();
    103     return 0;
    104 }
    View Code

    3442: 学习小组

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 176  Solved: 73
    [Submit][Status][Discuss]

    Description

    【背景】
    坑校准备鼓励学生参加学习小组。
    【描述】
        共有n个学生,m个学习小组,每个学生有一定的喜好,只愿意参加其中的一些学习小组,但是校领导为学生考虑,规定一个学生最多参加k个学习小组。财务处的 大叔就没那么好了,他想尽量多收钱,因为每个学生参加学习小组都要交一定的手续费,不同的学习小组有不同的手续费。然而,事与愿违,校领导又决定对学习小 组组织者进行奖励,若有a个学生参加第i个学习小组,那么给这个学习小组组织者奖励Ci*a^2元。在参与学生(而不是每个学习小组的人数总和)尽量多的 情况下,求财务处最少要支出多少钱(若为负数,则输出负数)(支出=总奖励费-总手续费)。

    Input

    输 入有若干行,第一行有三个用空格隔开的正整数n、m、k。接下来的一行有m个正整数,表示每个Ci。第三行有m个正整数,表示参加每个学习小组需要交的手 续费Fi。再接下来有一个n行m列的矩阵,表若第i行j列的数字是1,则表示第i个学生愿意参加第j个学习小组,若为0,则为不愿意。

    Output

     
    输出只有一个整数,为最小的支出。

    Sample Input


    3 3 1
    1 2 3
    3 2 1
    111
    111
    111

    Sample Output


    -2
    【样例解释】
    参与学生最多为3,每个学生参加一个学习小组,若有两个学生参加第一个学习小组,一个学生参加第二个学习小组(一定要有人参加第二个学习小组),支出为-2,可以证明没有更优的方案了。
    【数据范围与约定】
    100%的数据,0<n≤100,0<m≤90,0<k≤m,0<Ci≤10,0<Fi≤100。

    HINT

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    WinService12r2系统加固-3389端口与端口安全
    WinService12r2系统加固-账户管理与服务安全
    渗透测试常用工具-stunnel内网穿透
    渗透测试常用工具-ptunnel内网穿透
    报错注入函数
    常见绕过disable_function(抄录)linux系统。windows系统大概只有com组件
    nmap(抄录)
    php回调木马
    NoSql注入小测试。
    日志:记一次网页篡改(从开始到质保)一个渗透工作者的工作之路
  • 原文地址:https://www.cnblogs.com/Tunix/p/4354843.html
Copyright © 2011-2022 走看看