hdu6787(根据喜欢程度分配得最大总价值,最大费用最大流)

题:http://acm.hdu.edu.cn/showproblem.php?pid=6779

题意:给定a,b,c三种饮料数目和n个人,每个人有喜欢的饮料排名,价值依次是1、2、3,(最多6种类型的人)问分配后得到的最大总价值是多少。

分析:建边:1、源点向6类人建容量为这一类人出现的数目,费用为0;

      2、6类人分别向3种饮料建容量为无穷,费用为喜欢价值的负数;

      3、3种饮料向汇点建容量为饮料数目,费用为0。

   跑费用流。

#include<bits/stdc++.h>
using namespace std;
const int M=2e5+5;
const int inf=0x3f3f3f3f;
struct node{
    int u,v,w,cost,nextt;
}e[M];
int mincost;
int head[M],cur[M],dis[M],vis[12],tot,s,t;
void addedge(int u,int v,int w,int cost){
    e[tot].u=u;
    e[tot].v=v;
    e[tot].w=w;
    e[tot].cost=cost;
    e[tot].nextt=head[u];
    head[u]=tot++;
    e[tot].u=v;
    e[tot].v=u;
    e[tot].w=0;
    e[tot].cost=-cost;
    e[tot].nextt=head[v];
    head[v]=tot++;
}
bool bfs(){
    for(int i=0;i<=t;i++)
        dis[i]=inf;
    queue<int>que;
    que.push(s);
    dis[s]=0;
    while(!que.empty()){
        int u=que.front();
        que.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=e[i].nextt){
            int v=e[i].v;
            if(e[i].w&&dis[u]+e[i].cost<dis[v]){
                dis[v]=dis[u]+e[i].cost;
                if(!vis[v]){
                    vis[v]=1;
                    que.push(v);
                }
            }
        }
    }
    return dis[t]!=inf;
}
int dfs(int u,int fl){
    if(u==t)
        return fl;
    int ans=0;
    vis[u]=1;
    for(int i=cur[u];~i;i=e[i].nextt){
        int v=e[i].v;
        if(dis[v]==dis[u]+e[i].cost&&!vis[v]&&e[i].w){
            cur[u]=i;
            int x=dfs(v,min(e[i].w,fl-ans));
            e[i].w-=x;
            e[i^1].w+=x;
            ans+=x;
            mincost+=x*e[i].cost;
            if(ans==fl)
                break;
        }
    }
    vis[u]=0;
    return ans;
}
void MCMF(){
    while(bfs()){
        for(int i=0;i<=t;i++)
            cur[i]=head[i];
        dfs(s,inf);
    }
}
string tmp[]={"012","021","102","120","201","210"};
int drink[]={7,8,9};
map<string,int>mp;
int a[4];
int main(){
    int T;
    cin>>T;
    while(T--){
        memset(head,-1,sizeof(head));
        mp.clear();
        mincost=0;
        int n;
        cin>>n>>a[0]>>a[1]>>a[2];
        for(int i=1;i<=n;i++){
            string s;
            cin>>s;
            mp[s]++;
        }
        s=0,t=10;
        for(int i=0;i<6;i++){
            if(mp[tmp[i]]==0)
                continue;
            addedge(s,i+1,mp[tmp[i]],0);
            for(int j=0;j<3;j++){
                addedge(i+1,drink[tmp[i][j]-'0'],inf,j-3);
                ///cout<<tmp[i][j]<<"!!"<<drink[j]<<endl;
            }

        }
        for(int i=0;i<3;i++)
            if(a[i])
                addedge(drink[i],t,a[i],0);
        MCMF();
        cout<<-mincost<<'\n';

    }
    return 0;
}
View Code

 

posted @ 2020-07-27 10:20  starve_to_death  阅读(138)  评论(0编辑  收藏  举报