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可以一个人也不带。

输入输出样例

输入样例#1: 复制
2 3
10 1 2 0
25 2 3 0
5 6 7
输出样例#1: 复制
17

说明

对于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;
}
原文地址:https://www.cnblogs.com/lovewhy/p/8625925.html