P3410 拍照
漂亮小姐姐点击就送:https://www.luogu.org/problemnew/show/P3410
题目描述
小B有n个下属,现小B要带着一些下属让别人拍照。
有m个人,每个人都愿意付给小B一定钱让n个人中的一些人进行合影。如果这一些人没带齐那么就不能拍照,小B也不会得到钱。
注意:带下属不是白带的!!!对于每个下属,如果他带了那么小B需要给他一些钱,保证当他拍照时配合。
请问,小B的净收益最多是多少。
输入输出格式
输入格式:
第1行有2个正整数m和n(0<m,n<=100)。接下来的m行,每行是一个要求拍照的人的有关数据。第一个数是他同意支付该合影的费用;接着是该合影需要的若干下属的编号,以一个0作为行的结束标记。最后一行的n个数是带每个下属的费用。
输出格式:
一个数,表示最大收益。小B可以一个人也不带。
输入输出样例
说明
对于10%的数据每个人都要求让全部n个人合影
对于30%的数据n<=15 m<=15
另有10%的数据答案为0
对于50%的数据n<=40 m<=40
另有10%的数据每个人只愿意拍一个人
对于100%的数据m,n<=100
//源点向合影连边,边权为得到的钱 //合影向人连边,边权为inf, //把人拆点,边权为带这个人要付的钱,防止加多次 //人向汇点连边,边权为inf //先把能赚的钱全都加起来,也就是所有拍照的报酬 //然后跑dinic,算出来的是最小的花费 //就是说,如果拍照得到的钱小于带人的钱,跑出来的就是拍照的钱 //如果拍照的钱大于带人的钱,跑出来的就是带人的钱 //这样一减就是利润。 //我也不知道怎么描述,反正图画出来非常清晰 #include<iostream> #include<cstdio> #include<cstring> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<vector> using namespace std; const int N=1e4+5; const int INF=0x7fffffff; int n,m,S,T; int a,p; int c[N]; int head[N],num_edge; struct Edge { int v,flow,nxt; }edge[N<<1]; vector<int> vec[N]; inline int read() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) f=c=='-'?-1:f; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num*f; } inline void add_edge(int u,int v,int flow) { edge[++num_edge].v=v; edge[num_edge].flow=flow; edge[num_edge].nxt=head[u]; head[u]=num_edge; } int dep[N]; inline bool bfs() { memset(dep,0,sizeof(dep)); queue<int> que; que.push(S),dep[S]=1; int now,v; while(!que.empty()) { now=que.front(),que.pop(); for(int i=head[now];i;i=edge[i].nxt) { if(edge[i].flow) { v=edge[i].v; if(!dep[v]) { dep[v]=dep[now]+1; if(v==T) return 1; que.push(v); } } } } return 0; } int dfs(int now,int flow) { if(now==T) return flow; int v,outflow=0,tmp; for(int i=head[now];i;i=edge[i].nxt) { if(edge[i].flow) { v=edge[i].v; if(dep[v]!=dep[now]+1) continue; tmp=dfs(v,min(flow,edge[i].flow)); if(tmp) { edge[i].flow-=tmp; edge[i^1].flow+=tmp; outflow+=tmp; flow-=tmp; if(!flow) return outflow; } } } dep[now]=0; return outflow; } int Flow; int main() { num_edge=1; //教训!!! m=read(),n=read(); T=m+1+n<<1; for(int i=1;i<=m;++i) { while("why") { a=read(); if(!a) break; vec[i].push_back(a); } Flow+=vec[i][0]; } for(int i=1;i<=n;++i) { a=read(); // sum+=a; p=i<<1; add_edge(p-1,p,a); add_edge(p,p-1,0); add_edge(p,T,INF); add_edge(T,p,0); } for(int i=1;i<=m;++i) { p=i+n<<1; add_edge(S,p,vec[i][0]); add_edge(p,S,0); for(int j=1;j<vec[i].size();++j) { add_edge(p,vec[i][j]*2-1,INF); add_edge(vec[i][j]*2-1,p,0); } } while(bfs()) { Flow-=dfs(S,INF); } if(Flow<=0) printf("0"); else printf("%d",Flow); return 0; }