zoukankan      html  css  js  c++  java
  • CodeForces

    题目大意:

    见题面

    思路:

    一道很普通的mcmf,取一个学生的a值或者b值可以用流量来表示,即每个学生有1的流量。题目中我要求输出对与每个学生的被选择情况,我们可以通过遍历学生的正向边或者反向边的流量得出学生的被选择情况。

    Code:
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL N = 3010;
    struct node
    {
    	LL v, flow, cost, next;
    }edge[N*N];
    LL head[N], dis[N], vis[N], pre[N], rec[N], cnt;
    queue<LL> q;
    inline void init()
    {
    	cnt = 0;
    	memset(head, -1, sizeof(head));
    }
    inline void add_edge(LL u, LL v, LL f, LL c)
    {
    	edge[cnt].v = v; edge[cnt].flow = f; edge[cnt].cost = c;
    	edge[cnt].next = head[u]; head[u] = cnt++;
    	edge[cnt].v = u; edge[cnt].flow = 0; edge[cnt].cost = -c;
    	edge[cnt].next = head[v]; head[v] = cnt++;
    }
    LL SPFA(LL s, LL t)
    {
    	memset(dis, 0x3f, sizeof dis);
    	memset(vis, 0, sizeof vis);
    	while(!q.empty()) q.pop();
    	q.push(s); dis[s] = 0; vis[s] = 1;
    	while(!q.empty())
    	{
    		LL tp = q.front(); q.pop();
    		vis[tp] = 0;
    		LL k = head[tp];
    		while(k != -1)
    		{
    			if(dis[edge[k].v] > dis[tp] + edge[k].cost && edge[k].flow)
    			{
    				dis[edge[k].v] = dis[tp] + edge[k].cost;
    				pre[edge[k].v] = tp; rec[edge[k].v] = k;
    				if(vis[edge[k].v] == 0)
    				{
    					vis[edge[k].v] = 1;
    					q.push(edge[k].v);
    				}
    			}
    			k = edge[k].next;
    		}
    	}
    	if(dis[t] == INF) return 0;
    	return 1;
    }
    pair<LL, LL> Mcmf(LL s, LL t)
    {
    	LL minflow, k, mincost = 0, maxflow = 0;
    	while(SPFA(s, t))
    	{
    		k = t; minflow = INF;
    		while(k != s)
    		{
    			minflow = min(minflow, edge[rec[k]].flow);
    			k = pre[k];
    		}
    		k = t; maxflow += minflow;
    		while(k != s)
    		{
    			mincost += minflow*edge[rec[k]].cost;
    			edge[rec[k]].flow -= minflow;
    			edge[rec[k]^1].flow += minflow;
    			k = pre[k];
    		}
    	}
    	return make_pair(maxflow, mincost);
    }
    
    LL a[N], b[N];
    vector<LL> qa;
    vector<LL> qb;
    
    int main()
    {
    	init(); // do not forget it
    	LL n, m, s, t, pp, ps, valp, vals;
    	cin >> n >> valp >> vals;
    	s = 0;
    	pp = n + 1;
    	ps = n + 2;
    	t = n + 3;
    	for (LL i = 1; i <= n; i++) cin >> a[i];
    	for (LL i = 1; i <= n; i++) cin >> b[i];
    	for (LL i = 1; i <= n; i++) {
    		add_edge(s, i, 1, 0);
    		add_edge(i, pp, 1, -a[i]);
    		add_edge(i, ps, 1, -b[i]);
    	}
    	add_edge(pp, t, valp, 0);
    	add_edge(ps, t, vals, 0); 
    	pair<LL, LL> ans = Mcmf(s, t);
    	cout << -1LL * ans.second << endl;
    	for (LL i = 1; i <= n; i++) {
    		for (LL j = head[i]; ~j; j = edge[j].next) {
    			// if (edge[j].flow) continue; //not be used
                            if(!edge[j ^ 1].flow) continue; //反向边没有流量,说明正向边没有被使用
    			if (edge[j].v == pp) qa.push_back(i);
    			if (edge[j].v == ps) qb.push_back(i);
    		}
    	}
    	for (auto i : qa) cout << i << " ";
    	cout << endl;
    	for (auto i : qb) cout << i << " ";
    	cout << endl;
    	return 0;
    }
    
  • 相关阅读:
    python---1
    20190802—list、range、extend函数
    20190802—def定义函数
    20190802—import函数调用
    如何在EXCEL中将多个单元格内容合并到一个单元格中
    20190619—return函数的用法
    20190618—位置参数、默认参数、不定长参数
    excel 怎么计算单元格个数
    20190616——and和or使用方法、python运算符总结、python数据类型
    20190616——enumerate的用法
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/14303120.html
Copyright © 2011-2022 走看看