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
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。
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<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 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<int>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<dis[edge[i].to]) 44 { 45 dis[edge[i].to]=dis[x]+edge[i].cost; 46 pre[edge[i].to]=i; 47 if (!vis[edge[i].to]) 48 { 49 vis[edge[i].to]=1; 50 q.push(edge[i].to); 51 } 52 } 53 vis[x]=0; 54 } 55 return dis[e]!=INF; 56 } 57 58 void MCMF(int s,int e) 59 { 60 int fee=0,ans=0; 61 while (SPFA(s,e)) 62 { 63 if (dis[e]==0) break; 64 else ans++; 65 int d=INF; 66 for (int i=e; i!=s; i=edge[((pre[i]-1)^1)+1].to) 67 d=min(d,edge[pre[i]].flow); 68 for (int i=e; i!=s; i=edge[((pre[i]-1)^1)+1].to) 69 { 70 edge[pre[i]].flow-=d; 71 edge[((pre[i]-1)^1)+1].flow+=d; 72 } 73 fee+=d*dis[e]; 74 } 75 if (-fee==id_num) printf("%d ",ans); 76 else puts("no solution"); 77 } 78 79 void Tarjan(int x) 80 { 81 DFN[x]=Low[x]=++dfs_num; 82 Stack[++top]=x; Vis[x]=1; 83 for (int i=head[x]; i; i=edge[i].next) 84 if (!DFN[edge[i].to]) 85 { 86 Tarjan(edge[i].to); 87 Low[x]=min(Low[x],Low[edge[i].to]); 88 } 89 else if (Vis[edge[i].to]) 90 Low[x]=min(Low[x],DFN[edge[i].to]); 91 if (DFN[x]==Low[x]) 92 { 93 ID[x]=++id_num; Vis[x]=0; 94 while (Stack[top]!=x) 95 { 96 ID[Stack[top]]=id_num; 97 Vis[Stack[top--]]=0; 98 } 99 top--; 100 } 101 } 102 103 int main() 104 { 105 memset(&INF,0x7f,sizeof(INF)); 106 scanf("%d",&T); 107 while (T--) 108 { 109 Clear(); 110 scanf("%d%d%d%d",&n,&m,&A,&B); 111 for (int i=1; i<=A; ++i) scanf("%d",&a[i]); 112 for (int i=1; i<=B; ++i) scanf("%d",&b[i]); 113 for (int i=1; i<=m; ++i) scanf("%d%d",&u[i],&v[i]), add(u[i],v[i],0,0); 114 for (int i=1; i<=n; ++i) if (!DFN[i]) Tarjan(i); 115 memset(head,0,sizeof(head)); num_edge=0; 116 for (int i=1; i<=A; ++i) 117 add(s,ID[a[i]],INF,0), add(ID[a[i]],s,0,0); 118 for (int i=1; i<=B; ++i) 119 add(ID[b[i]]+5000,e,INF,0), add(e,ID[b[i]]+5000,0,0); 120 for (int i=1; i<=m; ++i) 121 if (ID[u[i]]!=ID[v[i]]) 122 add(ID[u[i]]+5000,ID[v[i]],INF,0), add(ID[v[i]],ID[u[i]]+5000,0,0); 123 for (int i=1; i<=id_num; ++i) 124 { 125 add(i,i+5000,1,-1); add(i+5000,i,0,1); 126 add(i,i+5000,INF,0); add(i+5000,i,0,0); 127 } 128 MCMF(s,e); 129 } 130 }