zoukankan      html  css  js  c++  java
  • 【刷题】洛谷 P4209 学习小组

    题目描述

    共有n个学生,m个学习小组,每个学生只愿意参加其中的一些学习小组,且一个学生最多参加k个学习小组。每个学生参加学习小组财务处都收一定的手续费,不同的学习小组有不同的手续费。若有a个学生参加第i个学习小组,财务处支付奖励 (C_i imes a^2) 元。在参与学生(而不是每个学习小组的人数总和)尽量多的情况下,求财务处最少要支出多少钱。

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:

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

    输出样例#1:

    -2

    说明

    100%的数据,0<n≤100,0<m≤90,0<k≤m,0< (C_i)​ ≤10,0< (F_i)​ ≤100。

    题解

    源点向所有学生连边,容量为 (k) ,费用为 (0) ,代表最多参加 (k) 个社团
    所有学生向汇点连边,容量为 (k-1) ,费用为 (0) ,代表学生至少要参加一个社团
    所有学生向能参加的社团连边,容量为 (1) ,费用为需要缴纳的费用的相反数
    所有社团向源点连边,连 (n) 条边,第 (i) 条边代表有 (i) 个学生加入了该社团,容量为 (1) ,费用为 (C imes (2i-1)) ,因为 (i^2-(i-1)^2=2i-1) ,这是第 (i) 个人加入后要多给的费用
    然后跑费用流即可

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=200+10,MAXM=MAXN*MAXN+10,inf=0x3f3f3f3f;
    int n,m,k,e=1,s,t,clk,answas,beg[MAXN],cur[MAXN],level[MAXN],vis[MAXN],p[MAXN],C[MAXN],F[MAXN],to[MAXM<<1],nex[MAXM<<1],cap[MAXM<<1],was[MAXM<<1];
    std::queue<int> q;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline void insert(int x,int y,int z,int w)
    {
    	to[++e]=y;
    	nex[e]=beg[x];
    	beg[x]=e;
    	cap[e]=z;
    	was[e]=w;
    	to[++e]=x;
    	nex[e]=beg[y];
    	beg[y]=e;
    	cap[e]=0;
    	was[e]=-w;
    }
    inline bool bfs()
    {
    	memset(level,inf,sizeof(level));
    	level[s]=0;
    	p[s]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		p[x]=0;
    		for(register int i=beg[x];i;i=nex[i])
    			if(cap[i]&&level[to[i]]>level[x]+was[i])
    			{
    				level[to[i]]=level[x]+was[i];
    				if(!p[to[i]])p[to[i]]=1,q.push(to[i]);
    			}
    	}
    	return level[t]!=inf;
    }
    inline int dfs(int x,int maxflow)
    {
    	if(x==t||!maxflow)return maxflow;
    	vis[x]=clk;
    	int res=0;
    	for(register int &i=cur[x];i;i=nex[i])
    		if((vis[x]^vis[to[i]])&&cap[i]&&level[to[i]]==level[x]+was[i])
    		{
    			int f=dfs(to[i],min(maxflow,cap[i]));
    			res+=f;
    			cap[i]-=f;
    			cap[i^1]+=f;
    			answas+=f*was[i];
    			maxflow-=f;
    			if(!maxflow)break;
    		}
    	return res;
    }
    inline void MCMF()
    {
    	while(bfs())clk++,memcpy(cur,beg,sizeof(cur)),dfs(s,inf);
    }
    int main()
    {
    	read(n);read(m);read(k);
    	s=n+m+1,t=s+1;
    	for(register int i=1;i<=n;++i)insert(s,i,k,0),insert(i,t,k-1,0);
    	for(register int i=1;i<=m;++i)read(C[i]);
    	for(register int i=1;i<=m;++i)
    		for(register int j=1;j<=n;++j)insert(i+n,t,1,C[i]*(2*j-1));
    	for(register int i=1;i<=m;++i)read(F[i]);
    	for(register int i=1;i<=n;++i)
    	{
    		char s[100];scanf("%s",s);
    		for(register int j=0;j<m;++j)
    			if(s[j]=='1')insert(i,j+1+n,1,-F[j+1]);
    	}
    	MCMF();
    	write(answas,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    2014年之新年新愿
    C#解析Xml的Dom和Sax方式性能分析
    WCF协议与绑定
    使用SqlServer数据批量插入
    跨站脚本攻击XSS
    疯狂的JSONP
    SQLiteOpenHelper
    Android常用的UI布局
    Android用户界面
    ListView
  • 原文地址:https://www.cnblogs.com/hongyj/p/9424535.html
Copyright © 2011-2022 走看看