如今的校园谈恋爱已是习以为常,这不,去上自习也要成双成对的。现在假设某班里有N对情侣从同一寝室楼出发,到达同一个教室上自习。途中,她们可能会经过长廊、静溪等一系列的景点观光游览。但情侣们不希望在途中碰到班里的其他情侣而扫了雅兴。现在给定包括寝室、教室、以及各个景点在内共有M个场景,以及这些场景之间的路径分布情况,请您帮忙为情侣们设计各自单独的散步路线。
输入
输入数据有多组,每组数据的第一行为2个正整数N(1<=N<=50)和M(2<=M<=50),分别表示共有N对情侣,M个场景,我们对场景从1~M进行编号。接下来的M行中,其中第i行的第一个数为正整数K,后面有K个正整数,表示与第i个场景之间有路径相连的场景编号。场景之间的路径是双向的,因此如果a与b之间有路径,那么b与a之间也必然有路径。我们始终假设:编号为1的场景是出发地——寝室楼,编号为2的场景是情侣们的目的地——自习教室。
当N和M均为0时输入结束。
输出
如果能够为情侣们设计出各自单独的散步路线(即除了出发地和目的地外,之间永远不会碰面),那么请输出YES,否则输出NO。
提示
样例的第一个实例对应的解决方案是:
1->3->2
1->4->2
1->5->2
把联通的路径设为1,直接求最大流就可以了。
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<string> #include<algorithm> #include<map> #include<queue> #include<vector> using namespace std; const int inf=0x7f7f7f7f; int n,m,G[55][55],flow[55],pre[55]; queue<int> q; int bfs(int s,int t) { while(!q.empty()) q.pop(); memset(pre,-1,sizeof pre); pre[s]=0,flow[s]=inf; q.push(s); while(!q.empty()) { int p=q.front(); q.pop(); if(p==t)break; for(int u=1;u<=n;u++) { if(u!=s&&G[p][u]>0&&pre[u]==-1) { pre[u]=p; flow[u]=min(flow[p],G[p][u]); q.push(u); } } } if(pre[t]==-1)return -1; return flow[t]; } int EK(int s,int t) { int delta=0,tot=0; while(1) { delta=bfs(s,t); if(delta==-1)break; int p=t; while(p!=s) { G[pre[p]][p]-=delta; G[p][pre[p]]+=delta; p=pre[p]; } tot+=delta; } return tot; } int main() { int i,j,t,tl; while(scanf("%d%d",&m,&n)) { if(n==0&&m==0)break; memset(G,0,sizeof G); memset(flow,0,sizeof flow); for(i=1;i<=n;i++) { scanf("%d",&t); for(j=0;j<t;j++) { scanf("%d",&tl); G[i][tl]=G[tl][i]=1; } } //printf("%d\n",EK(1,2)); int sum=EK(1,2); if(sum>=m) printf("YES\n"); else printf("NO\n"); } }