• CCPC-Wannafly Summer Camp #1——A——Birthday(最小费用流)


    时间限制: 1 Sec  内存限制: 256 MB

    题目描述

    恬恬的生日临近了。宇扬给她准备了一个大蛋糕。

    正如往常一样,宇扬在蛋糕上插了n支蜡烛,并把蛋糕分为m个区域。因为某种原因,他必须把第i根蜡烛插在第ai个区域或第bi个区域。区域之间是不相交的。宇扬在一个区域内同时摆放x支蜡烛就要花费x2的时间。宇扬布置蛋糕所用的总时间是他在每个区域花的时间的和。

    宇扬想快些见到恬恬,你能告诉他布置蛋糕最少需要多少时间吗?

    输入

    第一行包含两个整数nm(1 ≤ n ≤ 50, 2 ≤ m ≤ 50)。

    接下来n行,每行两个整数ai, bi(1 ≤ ai, bim)。

    输出

    一个整数表示答案。

    样例输入

    3 3
    1 2
    1 2
    1 2

    样例输出

    5

    题解:

    老规矩建超级源点和超级汇点,源点到每根蜡烛之间建一条边,流量为1费用为0。根据输入,建立蜡烛和蛋糕区域之间的边,流量为1,费用为0。每块蛋糕区域和汇点间建立50条边,流量都为1,费用为(1,3,5......99)

    代码:

     
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int MAXN = 5005; 
     
    struct Edge{
    	int value,flow,to,rev;
    	Edge(){}
    	Edge(int a,int b,int c,int d):to(a),value(b),flow(c),rev(d){}
    };
     
    vector<Edge> E[MAXN];
     
    inline void Add(int from,int to,int flow,int value){
    	E[from].push_back(Edge(to,value,flow,E[to].size()));
    	E[to].push_back(Edge(from,-value,0,E[from].size()-1));
    }
     
    bool book[MAXN];//用于SPFA中标记是否在queue中 
    int cost[MAXN];//存费用的最短路径 
    int pre[MAXN];//存前节点 
    int pree[MAXN];//存在前节点的vector中的下标 
     
    bool Spfa(int from,int to){
    	memset(book,false,sizeof book);
    	memset(cost,INF,sizeof cost);
    	book[from] = true;
    	cost[from] = 0;
    	queue<int> Q;
    	Q.push(from);
    	while(!Q.empty()){
    		int t = Q.front();
    		book[t] = false;
    		Q.pop();
    		for(int i=0 ; i<E[t].size() ; ++i){
    			Edge& e = E[t][i];
    			if(e.flow > 0 && cost[e.to] > cost[t] + e.value){
    				cost[e.to] = cost[t] + e.value;
    				pre[e.to] = t;
    				pree[e.to] = i;
    				if(book[e.to] == false){
    					Q.push(e.to);
    					book[e.to] = true;
    				}
    			}
    		}
    	}
    	return cost[to] != INF;
    }
     
    int Work(int from,int to){
    	int sum = 0;
    	while(Spfa(from,to)){
    		int mflow = INF;//SPFA找到的最短路径的最小容量 
    		int flag = to;
    		while(flag != from){
    			mflow = min(mflow,E[pre[flag]][pree[flag]].flow);
    			flag = pre[flag];
    		}
    		flag = to;
    		while(flag != from){
    			sum += E[pre[flag]][pree[flag]].value * mflow;
    			E[pre[flag]][pree[flag]].flow -= mflow;
    			E[flag][E[pre[flag]][pree[flag]].rev].flow += mflow;
    			flag = pre[flag];
    		}
    	}
    	return sum;
    }
    
    int main(){
    	
    	int N,M;
    	while(scanf("%d %d",&N,&M) == 2){
    		int a,b;
    		for(int i=1 ; i<=N ; ++i){
    			scanf("%d %d",&a,&b);
    			Add(i,a+N,1,0);
    			Add(i,b+N,1,0);
    			Add(0,i,1,0); 
    		}
    		for(int i=1 ; i<=M ; ++i){
    			for(int j=1 ; j<=99 ; j+=2){//99 = 2*50-1;
    				Add(i+N,M+N+1,1,j);
    			}
    		} 
    		printf("%d
    ",Work(0,M+N+1));
    		for(int i=0 ; i<=M+N+1 ; ++i)E[i].clear(); 
    	}
    	
    	return 0;
    }
     
  • 相关阅读:
    mysql面试题
    Zookeeper与Kafka基础概念和原理
    Docker资源限制
    企业级仓库harbor搭建
    基于容器制作镜像
    docker基础学习(一)
    docker往阿里云推镜像和打包镜像
    Dockfile制作镜像
    算法Sedgewick第四版-第1章基础-006一封装输出(文件)
    算法Sedgewick第四版-第1章基础-005一封装输入(可以文件,jar包里的文件或网址)
  • 原文地址:https://www.cnblogs.com/vocaloid01/p/9514020.html
Copyright © 2020-2023  润新知