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 #include2 #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