zoukankan      html  css  js  c++  java
  • 最小费用最大流

    链接:https://www.nowcoder.com/acm/contest/143/E
    来源:牛客网

    题目描述

    Nowcoder University has 4n students and n dormitories ( Four students per dormitory). Students numbered from 1 to 4n.

    And in the first year, the i-th dormitory 's students are (x1[i],x2[i],x3[i],x4[i]), now in the second year, Students need to decide who to live with.

    In the second year, you get n tables such as (y1,y2,y3,y4) denote these four students want to live together.

    Now you need to decide which dormitory everyone lives in to minimize the number of students who change dormitory.

    输入描述:

    The first line has one integer n.

    Then there are n lines, each line has four integers (x1,x2,x3,x4) denote these four students live together in the first year

    Then there are n lines, each line has four integers (y1,y2,y3,y4) denote these four students want to live together in the second year

    输出描述:

    Output the least number of students need to change dormitory.
    示例1

    输入

    复制
    2
    1 2 3 4
    5 6 7 8
    4 6 7 8
    1 2 3 5

    输出

    复制
    2

    说明

    Just swap 4 and 5

    备注:

    1<=n<=100

    1<=x1,x2,x3,x4,y1,y2,y3,y4<=4n

    It's guaranteed that no student will live in more than one dormitories.

    题意 : 给你 n 间宿舍第一年的成员分配情况,再给你第二年所有人想住哪个寝室的分配情况,询问你最小让几个人搬寝室可以达成要求?
    思路分析:网络流建图,跑个费用流即可
    重点是怎么建图,考虑第二年宿舍的分配情况,去分别匹配第一年的所有宿舍,去计算每种情况需要更换几个人,即为费用,流量是 1
    代码示例 :
    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e4;
    const int maxm = 1e5;
    const int inf = 0x3f3f3f3f;
    struct Edge
    {
        int to,next,flow,cost; // flow 表示水现有的流量
    }edge[maxm];
    int head[maxn],tol;
    int pre[maxn],dis[maxn];
    bool vis[maxn];
    int N; //节点个数,编号0->N-1 !全局变量 需要init赋值或主函数改变
    
    void init(int n)
    {
        N=n;
        tol = 0;
        memset(head,-1,sizeof(head));
    }
    
    void addedge(int u,int v,int cap,int cost) //边起点,终点,流量,费用
    {
        edge[tol].to = v;
        edge[tol].cost = cost;
        edge[tol].flow = cap;
        edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].to = u;
        edge[tol].cost = -cost;
        edge[tol].flow = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    }
    
    bool spfa(int s,int t)     //单源最短路径算法 可判断负环
    {
        queue<int >q;
        for(int i=0;i<N;i++)
        {
            dis[i] = inf;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v= edge[i].to;
                if(edge[i].flow && dis[v]>dis[u]+edge[i].cost)
                {
                    dis[v] = dis[u] + edge[i].cost;
                    pre[v] = i;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        if(pre[t]==-1) return false;
        else return true;
    }
    
    int MCMF(int s,int t,int &cost)  //MinCostMaxFlow  返回最大流,cost存最小费用
    {
        int flow = 0;
        cost = 0;
        while(spfa(s,t))
        {
            int Min = inf;
            for(int i= pre[t];i!=-1;i=pre[edge[i^1].to])
            {
                if(Min>edge[i].flow)
                    Min=edge[i].flow;
            }
            for(int i= pre[t];i!=-1;i=pre[edge[i^1].to])
            {
                edge[i].flow -= Min;
                edge[i^1].flow +=Min;
                cost += edge[i].cost*Min;
            }
            flow += Min;
        }
        return flow;
    }
    
    int n;
    struct node{
        int a, b, c, d;
    }arr[205];
    
    int fun(int x, int y){
        int res = 4;
        if (arr[x].a==arr[y].a || arr[x].a==arr[y].b || arr[x].a==arr[y].c || arr[x].a==arr[y].d) res--;
        if (arr[x].b==arr[y].a || arr[x].b==arr[y].b || arr[x].b==arr[y].c || arr[x].b==arr[y].d) res--;
        if (arr[x].c==arr[y].a || arr[x].c==arr[y].b || arr[x].c==arr[y].c || arr[x].c==arr[y].d) res--;
        if (arr[x].d==arr[y].a || arr[x].d==arr[y].b || arr[x].d==arr[y].c || arr[x].d==arr[y].d) res--; 
    
        return res;
    }
    
    int main() {
        
        cin >> n;
        for(int i = 1; i <= 2*n; i++){
            scanf("%d%d%d%d", &arr[i].a, &arr[i].b, &arr[i].c, &arr[i].d);
        }
        init(2*n+2);
        for(int i = 1; i <= n; i++){
            addedge(0, i, 1, 0);
            addedge(n+i, 2*n+1, 1, 0);
            for(int j = n+1; j <= 2*n; j++){
                addedge(i, j, 1, fun(i, j));
            }
        }
        int ans;
        MCMF(0, 2*n+1, ans);
        printf("%d
    ", ans);
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    uniapp 的组件 定义了 直接使用即可 。
    uniapp 关闭微信小程序的索引警告
    微信小程序 组件化开发 实现 导航分类文章 小程序
    微信小程序 向下滚动加载更多 和 上滑刷新的写法
    微信小程序 用 Pormise 封装 wx.request 请求
    ES6 再次学习 Promise语法(代码图解)
    Maven依赖排除及版本统一
    Maven依赖使用的范围
    SSM整合时的配置文件
    SSM整合时用到的maven依赖
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9433616.html
Copyright © 2011-2022 走看看