题解:P4209 学习小组
Solution
那个啥,平方很难处理。假如说增加一个人,平方从
然后是每个人至少选一个,如果明明能选却没选让给别人这不是最优的。首先拆点后每个人都有
原因:存在一种流法,就是每个人都只选一个,这样选出来的最大流一定保证人最多,所以其他与该最大流大小相等的也是符合要求的。
其他的建边很简单,不赘述。
:::success[code]
#include <bits/stdc++.h>
using namespace std;
struct node{int u,v,w,c;};
int n,m,k,s,t=381,x,f[95],d[385],flag[385],ans;
bool vis[385];
char ch;
vector<node> edges;
vector<int> e[385];
queue<int> q;
void add(int u,int v,int w,int c){
edges.push_back({u,v,w,c});
edges.push_back({v,u,0,-c});
e[u].push_back(edges.size()-2);
e[v].push_back(edges.size()-1);
}
bool bfs(){
memset(d,0x3f,sizeof d);
while(!q.empty()) q.pop();
d[s]=0,q.push(s);
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
for(auto to:e[u]){
int v=edges[to].v;
if(d[v]>d[u]+edges[to].c&&edges[to].w){
d[v]=d[u]+edges[to].c;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
return d[t]<1e9;
}
int dfs(int u,int flow){
if(u==t) return flow;
int sum=0;
vis[u]=1;
for(int i = flag[u];i<e[u].size();i++){
int v=edges[e[u][i]].v;
if(!vis[v]&&edges[e[u][i]].w&&d[v]==d[u]+edges[e[u][i]].c){
int tmp=dfs(v,min(flow,edges[e[u][i]].w));
sum+=tmp,flow-=tmp,edges[e[u][i]].w-=tmp,edges[e[u][i]^1].w+=tmp,ans+=edges[e[u][i]].c*tmp;
if(!flow) break;
}
}
vis[u]=0;
if(!sum) d[u]=-1;
return sum;
}
int dinic(){
while(bfs()){
memset(flag,0,sizeof flag);
dfs(s,1e9);
}
return ans;
}
signed main(){
cin>>n>>m>>k;
for(int i = 1;i<=m;i++){
cin>>x;
for(int j = 1;j<=2*n-1;j+=2)
add(i+n,t,1,j*x);
}
for(int i = 1;i<=m;i++) cin>>f[i];
for(int i = 1;i<=n;i++)
for(int j = 1;j<=m;j++){
cin>>ch;
if(ch=='1') add(i,j+n,1,-f[j]);
}
for(int i = 1;i<=n;i++) add(s,i,k,0),add(i,t,k-1,0);
cout<<dinic();
return 0;
}