UVA 11765 Component Placement 网络流 新姿势建图

题目链接:点击打开链接

题意:

给定n个物品, m个约束条件

把n个物品分到2个集合里

下面第一行表示i物品分到第一个集合里的花费

第二行表示分到第二个集合里的花费

第三行表示分物品的限制(1表示只能分到第一个集合,-1表示只能分到第二个集合,0无限制)

下面m行给出约束条件

u v cost 表示u v 两点必须能互相沟通,若两点已经在同一集合则花费为0 ,若不在同一集合则花费增加cost

问满足m个约束条件下的最小花费

思路:

首先感觉是网络流,==建图比较难想

用流量表示费用

1、若i点放入第一个集合,则向源点连一条流量为a[i]的边, 若放入第二个集合则向汇点连一条流量为b[i]的边

如此便可以使得一个点放入任意一个集合花费最小

2、对于约束条件 则向 u, v两点连一条无向的边,流量为cost

若u, v两点被第三行约束在同一集合,则这条边加了也不能增加流量,也就是费用增加0

若被约束在不同集合则相当于必然增加了cost

Orz

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

#define ll long long

#define N 100040
#define M 205000
#define inf 107374182
#define inf64 1152921504606846976
struct Edge{
	ll from, to, cap, nex;
}edge[M*2];//注意这个一定要够大 不然会re 还有反向弧

ll head[N], edgenum;
void add(ll u, ll v, ll cap, ll rw = 0){ //如果是有向边则:add(u,v,cap); 如果是无向边则:add(u,v,cap,cap);
	Edge E = { u, v, cap, head[u]};
	edge[ edgenum ] = E;
	head[u] = edgenum ++;

	Edge E2= { v, u, rw,  head[v]};
	edge[ edgenum ] = E2;
	head[v] = edgenum ++;
}
ll sign[N];
bool BFS(ll from, ll to){
	memset(sign, -1, sizeof(sign));
	sign[from] = 0;

	queue<ll>q;
	q.push(from);
	while( !q.empty() ){
		ll u = q.front(); q.pop();
		for(ll i = head[u]; i!=-1; i = edge[i].nex)
		{
			ll v = edge[i].to;
			if(sign[v]==-1 && edge[i].cap)
			{
				sign[v] = sign[u] + 1, q.push(v);
				if(sign[to] != -1)return true;
			}
		}
	}
	return false;
}
ll Stack[N], top, cur[N];
ll Dinic(ll from, ll to){
	ll ans = 0;
	while( BFS(from, to) )
	{
		memcpy(cur, head, sizeof(head));
		ll u = from;      top = 0;
		while(1)
		{
			if(u == to)
			{
				ll flow = inf, loc;//loc 表示 Stack 中 cap 最小的边
				for(ll i = 0; i < top; i++)
					if(flow > edge[ Stack[i] ].cap)
					{
						flow = edge[Stack[i]].cap;
						loc = i;
					}

					for(ll i = 0; i < top; i++)
					{
						edge[ Stack[i] ].cap -= flow;
						edge[Stack[i]^1].cap += flow;
					}
					ans += flow;
					top = loc;
					u = edge[Stack[top]].from;
			}
			for(ll i = cur[u]; i!=-1; cur[u] = i = edge[i].nex)//cur[u] 表示u所在能增广的边的下标
				if(edge[i].cap && (sign[u] + 1 == sign[ edge[i].to ]))break;
			if(cur[u] != -1)
			{
				Stack[top++] = cur[u];
				u = edge[ cur[u] ].to;
			}
			else
			{
				if( top == 0 )break;
				sign[u] = -1;
				u = edge[ Stack[--top] ].from;
			}
		}
	}
	return ans;
}
void init(){memset(head,-1,sizeof head);edgenum = 0;}

ll n, m;
ll a[N], b[N], c[N];
void input(){
    ll u, v, cos;
    cin>>n>>m;
    init();
    for(ll i = 1; i <= n; i++)scanf("%lld", &a[i]);
    for(ll i = 1; i <= n; i++)scanf("%lld", &b[i]);
    for(ll i = 1; i <= n; i++)scanf("%lld", &c[i]);
}
void work(){
    ll from = 0, to = n+10, u, v, cos;
    for(ll i = 1; i <= n; i++)
    {
        if(c[i]==1)
            add(from, i, a[i]), add(i, to, inf);
        else if(c[i]==-1)
            add(from, i, inf), add(i, to, b[i]);
        else add(from, i, a[i]), add(i, to, b[i]);
    }
    while(m--)
    {
        scanf("%lld %lld %lld",&u,&v,&cos);
        add(u, v, cos); add(v, u, cos);
    }
    cout<<Dinic(from, to)<<endl;
}
int main(){
    int T; cin>>T;
    while(T--){
        input();
        work();
    }
    return 0;
}

UVA 11765 Component Placement 网络流 新姿势建图

时间: 2024-10-21 12:30:42

UVA 11765 Component Placement 网络流 新姿势建图的相关文章

HDU 3036 Escape 网格图多人逃生 网络流||二分匹配 建图技巧

前言 在编程过程中总结归纳出来的一种编程经验,从而形成的设计思想称为设计模式. 设计模式有23种.它适用于所有的编程语言. 常用的有创新型的设计模式:简单工厂.抽象工厂和单例模式:行为型的设计模式:模板设计模式.观察者模式和命令模式:结构性的设计模式:适配器设计模式.代理模式(静态和动态两种,典型的有在spring的AOP编程中使用)和装饰器设计模式. 正文 单例模式(singleton) 保证一个类在内存中只能创建一个实例. 1.实现步骤: 1)将构造器私有化,即使用private修饰构造器

网络流建图/模型总结

网络流真的是一个什么强大的算法啦.令人头疼的是网络流的灵活应用之广泛,网络流的题目建图方式也是千奇百怪,所以蒟蒻打算总结一下网络流的建图方式.秉着不重复造轮子的原则(其实是博主又菜又想找个借口),网上大佬写的好的就直接贴网址了. (更新ing) 大佬强无敌的总结:https://www.cnblogs.com/victorique/p/8560656.html#autoid-1-10-3 最小割应用:https://wenku.baidu.com/view/87ecda38376baf1ffc4

网秦Q3财报现新姿势 老司机发力移动娱乐竟成网红

文/张书乐 日前,网秦公布了截至2016年9月30日的第三季度未经审计财务业绩.移动增值服务以同比增长74.6%至5,490万美元的成绩成为网秦营收贡献的最大板块. 老司机网秦作为国内最老牌的移动互联网"巨鳄"之一,竟然依靠移动娱乐实现了全面转型,而且网秦首席执行官许泽民更表示:"我们对移动娱乐业务领域取得的持续进展感到满意,随着2016年进入最后一个季度,我们会继续专注于执行我们的战略." 真的简单就是一个战略而已?网秦怎么就突然成了"网红"呢

HDU 4888 Redraw Beautiful Drawings 网络流 建图

题意: 给定n, m, k 下面n个整数 a[n] 下面m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵,若有多解输出Not Unique,若无解输出Impossible 思路:网络流,,, n行当成n个点,m列当成m个点 从行-列连一条流量为k的边,然后源点-行连一条a[i]的边, 列-汇点 流量为b[i] 瞎了,该退役了 T^T #include<stdio.h> #include<string.h> #include<iostream&

POJ 1149 网络流 合并建图

这个题目我敲了一个简单的EK,这不是难点 难点在于建图,按题目的要求 每个猪圈和顾客都建点的话,那也太多了...我看了Edelweiss里面的缩点方法才建好的图,哎,惭愧啊 实际那些猪圈根本不需要单独建点,猪圈无非就是向顾客输送流量 以及向同时开着的猪圈输送流量,这一步可以直接缩为,当某个猪圈被第一次打开,它里面的流量就全部输送给那个顾客那个点,而且可以叠加,因为每一次猪圈是可以互通的,而且猪圈本身是没有容量限制,如果有限制,那就还得再考虑. 此外,每次对猪圈的接下来的访问者都进行建边.用来输送

bzoj1656: [Usaco2006 Jan] The Grove 树木 (bfs+新姿势)

题目大意:一个n*m的图中,“.”可走,“X”不可走,“*”为起点,问从起点开始绕所有X一圈回到起点最少需要走多少步. 一开始看到这题,自己脑洞了下怎么写,应该是可过,然后跑去看了题解,又学会了一个新姿势... 上图是样例,红色笔迹是走法,需要走13步. 这显然是bfs题,问题是怎么让bfs绕这坨东西一圈,非常巧妙的思路,从任意一个X节点画一条射线与边界垂直,如下图所示. 当我们从右向左bfs的时候碰到这条线,就停止bfs:当我们绕了一圈从左向右bfs的时候碰到这条线,我们就继续走. dist[

POJ 3020 Antenna Placement(二分图建图训练 + 最小路径覆盖)

题目链接:http://poj.org/problem?id=3020 Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6692   Accepted: 3325 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobi

【原创】多dpi适配的新姿势

多dpi适配的新姿势 简介 Android中经常要通过ImageView进行图片资源显示.在加载图片时,首先要考虑的两个因素就是体验问题和性能问题. 其中,体验问题是指图片显示的是否正确(例如Universal-Image-Loader在适配Adapter图片资源时会导致图片显示错位),图片显示尺寸是否合适,分辨率是否合适等.本文重点介绍ImageView加载图片中的显示问题. 问题 在开发的过程中,一般会将不同分辨率的图片放置在不同的文件夹中,例如将三种同样内容不同分辨率的图片分别放置在dra

[UVA 10801]Lift Hopping[Dijkstra][建图]

题目链接:[UVA 10801]Lift Hopping[Dijkstra][建图] 题意分析: 从0层开始,一共有n台电梯供你到达目的地k层.每台电梯往上走一层都要消耗t[i]的时间,并且电梯只能在特定的楼层停下,换乘电梯要花费60s的时间,而且呢,你不能用楼梯上楼,只能搭电梯....(hentai!)问:最快到达楼层k的时间是多少?不能到达就输出-1. 解题思路: 这题技巧就是体现在建图上,图建好了,用dijkstra跑一遍就行了. 具体建图就是用mp[i][j]代表从楼层i到楼层j的最小距