博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ2893:征服王(费用流)
阅读量:6899 次
发布时间:2019-06-27

本文共 2396 字,大约阅读时间需要 7 分钟。

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。

Solution

打死白学家

首先第一感觉这个题很像最小路径覆盖……但他并不是一个$DAG$。所以我们自己动手丰衣足食把它缩成一个$DAG$。

现在变成了一个多起点多终点的最小路径覆盖问题。我们首先把一个点拆成$u$和$u'$,并且$u$连向$u'$一条流量为$1$,费用为1的边。

然后原图的边就$u'$连向$v$一条流量为$INF$,费用为$0$的边。

源点$S$向图中的起点$s$连流量为$INF$,费用为$0$的边,终点$t'$向图中的汇点$E$流量为$INF$,费用为$0$的边。

跑一边最大费用最大流。如果费用为点数那么说明每个点都经过了,答案为增广次数。

否则无解。

Code

1 #include
2 #include
3 #include
4 #include
5 #define N (10009) 6 using namespace std; 7 8 struct Edge{
int to,next,flow,cost;}edge[N*100]; 9 int DFN[N],Low[N],Stack[N],ID[N],Vis[N],top,dfs_num,id_num; 10 int T,n,m,A,B,a[N],b[N],u[N*10],v[N*10],x,INF,s,e=10000; 11 int dis[N],pre[N],vis[N]; 12 int head[N],num_edge; 13 queue
q; 14 15 void Clear() 16 { 17 memset(head,0,sizeof(head)); 18 memset(DFN,0,sizeof(DFN)); 19 memset(Low,0,sizeof(Low)); 20 memset(ID,0,sizeof(ID)); 21 memset(Vis,0,sizeof(Vis)); 22 num_edge=top=dfs_num=id_num=0; 23 } 24 25 void add(int u,int v,int l,int c) 26 { 27 edge[++num_edge].to=v; 28 edge[num_edge].next=head[u]; 29 edge[num_edge].flow=l; 30 edge[num_edge].cost=c; 31 head[u]=num_edge; 32 } 33 34 bool SPFA(int s,int e) 35 { 36 memset(dis,0x7f,sizeof(dis)); 37 memset(pre,-1,sizeof(pre)); 38 dis[s]=0; q.push(s); vis[s]=1; 39 while (!q.empty()) 40 { 41 int x=q.front(); q.pop(); 42 for (int i=head[x]; i; i=edge[i].next) 43 if (edge[i].flow && dis[x]+edge[i].cost

转载于:https://www.cnblogs.com/refun/p/10289275.html

你可能感兴趣的文章
V8十年故事:从农场诞生的星球最强JS引擎
查看>>
AI一周热闻:周志华获IEEE技术成就奖;英伟达发布最小AI计算机
查看>>
有赞透明多级缓存解决方案(TMC)设计思路
查看>>
使用Prometheus和Grafana实现SLO
查看>>
堆和栈
查看>>
Spotify希望自己擅于失败
查看>>
隐私和安全是macOS Mojave和Safari 12的第一要务
查看>>
《Agendashift》的作者访谈录(一)
查看>>
Kong 发布 Kong Brain 和 Kong Immunity,可进行智能自动化和适应性监控
查看>>
面试时,面试官到底在考察什么?
查看>>
网络协议必会知识点:互联网网络分层
查看>>
滴滴自研分布式NoSQL数据库Fusion的演进之路
查看>>
定制你的敏捷方法:以结果为导向
查看>>
2018双十一苏宁20+篇技术干货全整理
查看>>
我的2016年
查看>>
概览Visual Studio 15.3的第二个预览版
查看>>
Tensorflow 1.3版本更新概览
查看>>
Spark比拼Flink:下一代大数据计算引擎之争,谁主沉浮?
查看>>
jDays 2016综合报道
查看>>
通过Visual Studio为Linux编写C++代码
查看>>