2893: 征服王

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit:
156  Solved: 48
[Submit][Status][Discuss]

Description

虽然春希将信息传递给了雪菜,但是雪菜却好像完全不认得春希了。心急如焚的春希打开了第二世代机能,对雪菜的脑内芯片进行了直连-hack。
进入到雪菜内部的春希发现(这什么玩意。。),雪菜的脑部结构被分成了n个块落,并且一些块落之间被有向边连接着。由于四分五裂的脑部,雪菜关于春希的记忆也完全消失,春希为了恋人,启动了inversionprocess.
在inversion
process中,要想使雪菜回到正常状态,需要纳米机器人的帮助。纳米机器人可以从任意一个可以作为起点的块落出发进行修复,也可以在任意一个可以作为终点的块落结束修复(并不是到了某个终点就一定要停止)。春希希望所有的节点都能被修复(只要纳米机器人到过该点就算修复过),这样才能让雪菜重获新生。
作为纳米机器人1号的你能帮助春希算算至少需要多少个机器人才能拯救雪菜吗?
当然,如果无论如何都无法使得春希的愿望被满足的话,请输出”no
solution”(不包括引号)

Input

题目包含多组数据
第1行有一个正整数t,表示数据的组数。
第2行有两个正整数n、m,a,b,分别表示块落的数量、有向边的数量、起点的数量、终点的数量。
第3行有a个正整数,表示可以作为起点的块落。
第4行有b个正整数,表示可以作为终点的块落。
第5行至第m+4行,每行有两个正整数u、v,表示能从编号为u的块落到编号为v的块落。
之后以此类推。

Output

输出共有t行,每行输出对应数据的答案。

Sample Input

2
2 1 1 1
1
2
2 1
3
2 3 3
1 2 3
1 2 3
1 2
1 3

Sample Output

no
solution
2
【数据规模和约定】
对于30%的数据,满足n <= 10, m <=
100。
对于60%的数据,满足n <= 200, m <= 5000。
对于100%的数据,满足t<=10,n <=
1000, m <= 10000。

HINT

Source

Solution

一眼网络流,起点终点有限制的最小路径覆盖

一般的最小路径覆盖问题,是用二分图的方法去解

而这里,应该考虑另一种做法

对于有向图,先Tarjan缩点,重建图,然后求带下届的最小流即可

但是这里用的最大费用最大流,同时需要缩点,建图:

对于Tarjan后缩成的点,每个点拆成两个点,入点向出点连两条边,容量inf,费用0;容量1,费用1

原图中的点,缩成的点相连,容量inf,费用1

S到起始点缩成的点连容量inf,费用0

T到终止点缩成的点连容量inf,费用0

然后跑最大费用最大流,因为最大费用最大流每次增广的费用是严格从大到小的,所以增广次数既为答案

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxm 100100
#define maxn 2010
int n,m,A,B,t,ans,cost;
struct Edgenode{int to,next,cap,cost,from;}edge[maxm];
int head[maxn],cnt;
inline void add(int u,int v,int w,int c)
{
cnt++; edge[cnt].next=head[u]; head[u]=cnt;
edge[cnt].from=u; edge[cnt].to=v; edge[cnt].cap=w; edge[cnt].cost=c;
}
inline void insert(int u,int v,int w,int c)
{add(u,v,w,c); add(v,u,,-c);}
struct Roadnode{int to,next;}road[maxm];
int last[maxn],cnr;
inline void Add(int u,int v)
{
cnr++; road[cnr].next=last[u]; last[u]=cnr; road[cnr].to=v;
}
#define inf 0x7fffffff
int S,T; int dis[maxn]; queue<int>q; bool mark[maxn];
inline bool spfa()
{ memset(mark,,sizeof(mark));
for (int i=; i<=S; i++) dis[i]=-;
q.push(T); mark[T]=; dis[T]=;
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=head[now]; i; i=edge[i].next)
if (edge[i^].cap && dis[edge[i].to]<dis[now]+edge[i^].cost)
{
dis[edge[i].to]=dis[now]+edge[i^].cost;
if (!mark[edge[i].to])
mark[edge[i].to]=,q.push(edge[i].to);
}
mark[now]=;
// printf("%d %d %d\nhahahaha",now,he,ta);
}
return dis[S]!=-;
}
inline int dfs(int loc,int low)
{
mark[loc]=;
if (loc==T) return low;
int w,used=;
for (int i=head[loc]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==dis[loc]-edge[i].cost && !mark[edge[i].to])
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^].cap+=w; used+=w;
cost+=w*edge[i].cost; if (used==low) return low;
}
return used;
}
inline void zkw()
{
while (spfa())
{
int pre=cost;
mark[T]=;
while (mark[T])
{memset(mark,,sizeof(mark)); dfs(S,inf);}
insert(S,,,);
if (pre==cost) break; else ans++;
}
// printf("%d %d %d\n",cnt,cost,ans);
}
int stack[maxn],top,dfn[maxn],low[maxn],tot,qcnt,belong[maxn]; bool visit[maxn];
void Tarjan(int x)
{
dfn[x]=low[x]=++tot;
visit[x]=; stack[++top]=x;
for (int i=last[x]; i; i=road[i].next)
{
if (!dfn[road[i].to])
{
Tarjan(road[i].to);
if (low[road[i].to]<low[x]) low[x]=low[road[i].to];
}
else
if(visit[road[i].to] && dfn[road[i].to]<low[x])
low[x]=dfn[road[i].to];
}
if (dfn[x]==low[x])
{
int uu=;qcnt++;
while (x!=uu)
uu=stack[top--],visit[uu]=,belong[uu]=qcnt;
}
}
inline void init()
{
memset(dfn,,sizeof(dfn));
memset(head,,sizeof(head));
memset(last,,sizeof(last));
cnt=; cnr=top=tot=qcnt=cost=ans=;
}
int cans[maxn],cant[maxn];
inline void rebuild()
{
T=*qcnt+;S=T+;
for (int i=; i<=A; i++) insert(,belong[cans[i]],inf,);
for (int i=; i<=B; i++) insert(belong[cant[i]]+qcnt,T,inf,);
for (int u=; u<=n; u++)
for (int i=last[u]; i; i=road[i].next)
if (belong[u]!=belong[road[i].to])
insert(belong[u]+qcnt,belong[road[i].to],inf,);
for (int i=; i<=qcnt; i++) insert(i,i+qcnt,,),insert(i,i+qcnt,inf,);
insert(S,,,);
}
int main()
{
// freopen("sail.in","r",stdin);
// freopen("sail.out","w",stdout);
t=read();
while (t--)
{
init();
n=read(),m=read(),A=read(),B=read();
for (int i=; i<=A; i++) cans[i]=read();
for (int i=; i<=B; i++) cant[i]=read();
for (int u,v,i=; i<=m; i++) u=read(),v=read(),Add(u,v);
for (int i=; i<=n; i++) if (!dfn[i]) Tarjan(i);
rebuild();
zkw();
if (cost!=qcnt) puts("no solution");
else printf("%d\n",ans);
}
return ;
}

这题自己默默T成狗,改了好久

【BZOJ-2893】征服王 最大费用最大流(带下界最小流)的更多相关文章

  1. bzoj 2502 清理雪道(有源汇的上下界最小流)

    [题意] 有一个DAG,要求每条边必须经过一次,求最少经过次数. [思路] 有上下界的最小流.  边的下界为1,上界为无穷.构造可行流模型,先不加ts边跑一遍最大流,然后加上t->s的inf边跑 ...

  2. bzoj 4200: [Noi2015]小园丁与老司机【dp+有上下界最小流】

    洛谷上有个点死活卡不过去,不知道是哪里写丑了orz 参考:https://www.cnblogs.com/ditoly/p/BZOJ4200.html 从上往下dp,设f为不向左右走直接上去的值,g为 ...

  3. BZOJ 2502 清理雪道(有源汇上下界最小流)

    题面 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机, ...

  4. BZOJ 2502 清理雪道/ Luogu P4843 清理雪道 (有源汇上下界最小流)

    题意 有一个有向无环图,求最少的路径条数覆盖所有的边 分析 有源汇上下界最小流板题,直接放代码了,不会的看dalao博客:liu_runda 有点长,讲的很好,静心看一定能看懂 CODE #inclu ...

  5. BZOJ 1458 / Luogu P4311 士兵占领 (上下界最小流 / 直接最大流)

    做法1:上下界最小流 先来一发上下界最小流,思路比较暴力,就是把行和列看作n+mn+mn+m个点,(i,j)(i,j)(i,j)如果能占领就从第iii行向第jjj列连一条边,上界为1下界为0;然后从s ...

  6. sgu 176 Flow construction(有源汇的上下界最小流)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025 [模型] 有源汇点的上下界最小流.即既满足上下界又满足 ...

  7. BZOJ_2502_清理雪道_有源汇上下界最小流

    BZOJ_2502_清理雪道_有源汇上下界最小流 Description        滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道), ...

  8. 【Loj117】有源汇上下界最小流(网络流)

    [Loj117]有源汇上下界最小流(网络流) 题面 Loj 题解 还是模板题. #include<iostream> #include<cstdio> #include< ...

  9. SGU 176 Flow construction (有源有汇有上下界最小流)

    题意:给定 n 个点,m 条有向边,如果有向边的标号是1的话,就表示该边的上界下界都为容量 ,如果有向边的标号为0的哈,表示该边的下界为0,上界为容量 ,现在问,从 1 到 n 的最小流是多少,并输出 ...

随机推荐

  1. 学习下nginx负载均衡--深入理解nginx

    作为代理服务器,一般都需要向上游服务器转发请求.这里的负载均衡是指通过一种策略尽量把请求平均的分发都上游服务器 1.upstream 语法 upstream name {} 配置快: http 栗子( ...

  2. 用Javascript判断访问来源操作系统, 设备, 浏览器类型

    var browser = { os : function() { var u = navigator.userAgent; return {// 操作系统 linux: !!u.match(/\(X ...

  3. NOI2018准备Day7

    昨天没写,就不补了. 晚上追剧到3点,今天困死...... 上午做了一道水题,然后找一个程序的神奇的错误花了3个小时 下午做了3道递归吧,稍微难一点儿的黄金题就卡了 刚开始学递归时没多做题练练,现在 ...

  4. 字符串匹配(hash算法)

    hash函数对大家来说不陌生吧 ? 而这次我们就用hash函数来实现字符串匹配. 首先我们会想一下二进制数. 对于任意一个二进制数,我们将它化为10进制的数的方法如下(以二进制数1101101为例): ...

  5. JavaScript的TDD训练营环境搭建

    下周一准备去蹭听公司组织的javascript TDD训练营.以前只是零散的使用javascript,水平相当于小白,笨鸟先飞,提前把环境鼓捣一下. 步骤: 1.nodejs安装 到http://ww ...

  6. lecture8-RNN的训练方法之二三

    HInton第8课,之所以说之二三,是因为训练RNN的四种方法之一:长短时记忆在lecture7中介绍过了,这里介绍的是第二和第三种方法:HF优化和Echo (这个字觉得翻译成回声是不是欠妥,所以保留 ...

  7. opencv3-core之基本操作

    这一篇打算将core部分的例子说完,这都是基于<opencv2.4.9tutorial.pdf>中的core部分,其实这些例子后期都很稳定的,也就是说就算是2.3.1和2.4.10 ,这几 ...

  8. Android中的Semaphore

    信号量,了解过操作系统的人都知道,信号量是用来做什么的··· 在Android中,已经提供了Semaphore来帮助我们使用~ 那么,在开发中这家伙有什么用呢? 用的地方不多,但是却真的是好用至极! ...

  9. 写一个 nodejs npm应用 - webhere

    前言.没图不说话,先上图. What's webhere? 有没有遇到这样的场景:写程序的时候,需要访问一个文件,这个文件 需要是放到一台web服务器上,但是你不是开发的web应用. 所以呢,你不得不 ...

  10. jquery图片轮播效果(unslider)

    今天做网站(住建局网站)需要用到图片轮播,刚开始想借鉴DTCMS上的,查看CSS与页面代码,呵呵,不复杂,直接复制过来,结果调整半天,页面还是各种乱,没办法,网上找一个吧,于是找到了今天要说的这货un ...