Oooooooo AAAAE 【网络流最小点权覆盖】
Description
“Let the bass kick!O-oooooooooo AAAAE-A-A-I-A-U- JO-oooooooooooo AAE-O-A-A-U-U-A- E-eee-ee-eee AAAAE-A-E-I-E-A- JO-ooo-oo-oo-oo EEEEO-A-AAA-AAAA!”
LiMn2O4沉迷音乐游戏,每天都在摸鱼搓音游,而且是手机电脑两开花……为了帮助LiMn2O4尽快清醒过来,LiMn2O4答应skyer_hxx,只要skyer_hxx能写一个自动脚本来玩这个游戏,打败他的最高纪录,那么就不再摸鱼了。
这个游戏可以简化成:谱面由N个键和M条连线组成,每两个键之间有一个连线,玩家需要在键之间滑动,且连线的方向是固定的,玩家每次选择一个键,把所有从这个键出发的连线都消除掉,花费为ai,也可以将每个结束在这个点的连线消除,花费Bi。不用担心,LiMn2O4的手指足够多。最后让连线全部消失,得分就是总花费。花费越少,分数越高。
skyer_hxx何许人也,怎么会怕这点小问题?但是他现在很忙,需要你的帮助。请你对于给出的谱面,求出最小的花费。
Input
第一行有两个正整数N,M,含义同题目描述
接下来两行,第一行有N个正整数 ,代表从键i正向划到别的键需要的花费
第二行有N个正整数 ,代表从其他的键划到第i个键需要的花费
接下来M行,每一行都有两个正整数u,v,代表键u,v之间有一条u到v的连线。两个键之间可能有多个连线,同一个键之间也可能有连线。
Output
输出最小的花费,占一行。
Sample Input
3 2
1 2 1
2 1 2
1 2
1 3
Sample Output
2
我的想法:
1.首先想用贪心算法,存每条边然后比较out[a], in[b]。不过错的很离谱,答案要大了很多。原因是因为没看清楚题目。也就是上面我标红的地方。对于每个点只能计算一次最小的点权,用贪心的话点有重复也会重复计算进去。
2.最小点权覆盖集:从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。最大点权独立集:在二分图中找到权值和最大的点集,使得它们之间两两没有边。
3.借鉴了题解的思路。才知道是网络流最小点权覆盖问题。设立源点s和t,s连边到点i,容量为i点的权值;点j连边到t,容量为j点权值;原二分图中的边容量为INF,求最大流即为最小点权覆盖。
4.扩展:最大点权独立集可转化为最小点权覆盖问题,最大点权独立集 = 总权值 - 最小点权覆盖集
题解思路:
经典的网络流最小点权覆盖问题,首先拆点,分成左右两部分,源点向所有左节点连一条边,流量为删除出边的花费。所有右节点向汇点连一条边,流量为删除入边的费用。对于每条输入给定的边<u,v>,其在左边的点为u,v,右边的点为u’,v’,那么我们连一条<u,v’>的边,流量为∞(正无穷才不会对可行流上最小的容量产生限制)。跑一边最大流,得到的答案就是最小的费用。
首先,如果没有花费的话,这道题就是简单的最小点覆盖集。加上了点权之后,我们就要将最小割的思想融合进去。要注意费用,一定要符合S->T的顺序
代码:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
const int inf = 0x3f3f3f3f;
using namespace std; int n, m, cnt, head[];
int arr[], brr[];
int dep[];
queue<int>Q; struct Edge
{
int to, next;
int w;
}edge[]; void add(int a, int b, int w)
{
edge[cnt].to = b;
edge[cnt].w = w;
edge[cnt].next = head[a];
head[a] = cnt ++;
} int bfs(int st, int ed) //dinic算法的优化之处,先进行分层
{
if(st == ed)
return ;
while(!Q.empty())
Q.pop();
mem(dep, -); //每次都初始化为未被分层
dep[st] = ; //源点设置层次为1
Q.push(st);
while(!Q.empty())
{
int index = Q.front();
Q.pop();
for(int i = head[index]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(dep[to] == - && edge[i].w > )
{
dep[to] = dep[index] + ;
Q.push(to);
}
}
}
return dep[ed] != -;//返回是否成功分层
} int dfs(int now, int ed, int cnt)
{
if(now == ed)
return cnt;
for(int i = head[now]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(dep[to] == dep[now] + && edge[i].w > )
{
int flow = dfs(to, ed, min(edge[i].w, cnt));
if(flow > )
{
edge[i].w -= flow;
edge[i ^ ].w += flow;
return flow;
}
}
}
return -;
} void dinic(int st, int ed)
{
long long ans = ;
while(bfs(st, ed))
{
while()
{
int inc = dfs(st, ed, inf);
if(inc == -)
break;
ans += inc;
}
}
printf("%lld\n", ans);
} int main()
{
mem(head, -);
scanf("%d%d", &n, &m);//n个点,m条边
for(int i = ; i <= n; i ++) //起点向汇点 2 * n + 1建边
{
scanf("%d", &arr[i]);
add(i + n, * n + , arr[i]);
add( * n + , i + n, );
}
for(int i = ; i <= n; i ++)//源点 0 向终点建边
{
scanf("%d", &brr[i]);
add(, i, brr[i]);
add(i, , );
}
for(int i = ; i <= m; i ++)//从源点方向向汇点方向建边
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b + n, inf);
add(b + n, a, );
}
//从源点向汇点跑一遍最大流
dinic(, * n + );
return ;
}
Oooooooo AAAAE 【网络流最小点权覆盖】的更多相关文章
- POJ2125 Destroying The Graph (最小点权覆盖集)(网络流最小割)
Destroying The Graph Time Limit: 2000MS Memo ...
- hdu 1565&hdu 1569(网络流--最小点权值覆盖)
方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- POJ - 2125 Destroying The Graph (最小点权覆盖)
题意:给一张图,现在要删去所有的边,删去一个点的所有入边和所有出边都有其对应\(W_{i+}\)和\(W_{i-}\).求删去该图的最小花费,并输出解 分析:简而言之就是用最小权值的点集去覆盖所有的边 ...
- POJ - 3308 Paratroopers (最小点权覆盖)
题意:N*M个格点,K个位置会有敌人.每行每列都有一门炮,能打掉这一行(列)上所有的敌人.每门炮都有其使用价值.总花费是所有使用炮的权值的乘积.求最小的总花费. 若每门炮的权值都是1,就是求最小点覆盖 ...
- POJ 2125 Destroying the Graph 二分图最小点权覆盖
Destroying The Graph Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8198 Accepted: 2 ...
- POJ3308 Paratroopers(最小割/二分图最小点权覆盖)
把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...
- POJ2125 Destroying The Graph(二分图最小点权覆盖集)
最小点权覆盖就是,对于有点权的有向图,选出权值和最少的点的集合覆盖所有的边. 解二分图最小点权覆盖集可以用最小割: vs-X-Y-vt这样连边,vs和X部点的连边容量为X部点的权值,Y部和vt连边容量 ...
- POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)
题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...
- POJ 3308 Paratroopers (对数转换+最小点权覆盖)
题意 敌人侵略r*c的地图.为了消灭敌人,可以在某一行或者某一列安置超级大炮.每一个大炮可以瞬间消灭这一行(或者列)的敌人.安装消灭第i行的大炮消费是ri.安装消灭第j行的大炮消费是ci现在有n个敌人 ...
随机推荐
- Luogu P1951 收费站_NOI导刊2009提高(2) 二分 最短路
思路:二分+最短路 提交:1次 题解: 二分最后的答案. $ck()$: 对于每次的答案$md$跑$s,t$的最短路,但是不让$c[u]>md$的点去松弛别的边,即保证最短路不经过这个点.最后$ ...
- *p++=i怎么理解?
#include<stdio.h> void fibonacci(int *p,int n) { *p++=1; *p++=1; while(n>2) { *p++=*(p-1)+* ...
- Yet Another Division Into Teams
E. Yet Another Division Into Teams 首先要想明白一个东西,就是当一个小组达到六个人的时候,它一定可以拆分成两个更优的小组. 这个题可以用动态规划来写,用一个数组来保存 ...
- 使用shell脚本完成自动化部署及秒级回滚
一.部署机代码目录结构 使用www用户进行代码部署,所有部署机上需要创建www用户,并赋予根目录权限,同时配置公私钥认证建立信任关系. [www@ansible-node1 deploy]$ tree ...
- JavaWeb_(Spring框架)Spring整合Hibernate
Dao层类要继承HibernateDaoSupport.java父类 原先使用Hibernate框架hibernate.cfg.xml配置数据库 <hibernate-configuration ...
- [51nod1789] 跑得比谁都快
题面 题解 设\(f[i]\)为根节点到\(i\)的最小耗时 设\(S\)为\(i\)的祖先集合, 可以得到 \[ f[i] = min(f[j] + (i - j)^p),j \in S \] 对于 ...
- Linux设备驱动程序 之 装载和卸载模块
前置说明 本文例子中涉及两个模块hello.ko和world.ko,其中hello导出符号供world使用: insmod 该命令将模块的代码和数据装入内核,然后使用内核的符号表继续模块中任何未解析的 ...
- antd源码分析之——折叠面板(collapse)
官方文档 https://ant.design/components/collapse-cn/ 目录 一.antd中的collapse 代码目录 1.组件结构图(♦♦♦重要) 2.源码节选:antd/ ...
- typescript简单的应用
简单来说typescript就是新增一下方法,以及增加类型判断 一.普通的类型判断 1.布尔类型(boolean) let isDone: boolean = false let createdByB ...
- excel导出显示默认格子
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:o ...