Shooting Contest
Time Limit: 1000MS | Memory Limit: 10000K | |||
Total Submissions: 4097 | Accepted: 1499 | Special Judge |
Description
Welcome to the Annual Byteland Shooting Contest. Each competitor will shoot to a target which is a rectangular grid. The target consists of r*c squares located in r rows and c columns. The squares are coloured white or black. There are exactly two white squares and r-2 black squares in each column. Rows are consecutively labelled 1,..,r from top to bottom and columns are labelled 1,..,c from left to right. The shooter has c shots.
A volley of c shots is correct if exactly one white square is hit in each column and there is no row without white square being hit. Help the shooter to find a correct volley of hits if such a volley exists.
Example
Consider the following target:
Volley of hits at white squares in rows 2, 3, 1, 4 in consecutive columns 1, 2, 3, 4 is correct.
Write a program that: verifies whether any correct volley of hits exists and if so, finds one of them.
A volley of c shots is correct if exactly one white square is hit in each column and there is no row without white square being hit. Help the shooter to find a correct volley of hits if such a volley exists.
Example
Consider the following target:
Volley of hits at white squares in rows 2, 3, 1, 4 in consecutive columns 1, 2, 3, 4 is correct.
Write a program that: verifies whether any correct volley of hits exists and if so, finds one of them.
Input
The first line of the input contains the number of data blocks x, 1 <= x <= 5. The following lines constitute x blocks. The first block starts in the second line of the input file; each next block starts directly after the previous one.
The first line of each block contains two integers r and c separated by a single space, 2 <= r <= c <= 1000. These are the numbers of rows and columns, respectively. Each of the next c lines in the block contains two integers separated by a single space. The integers in the input line i + 1 in the block, 1 <= i <= c, are labels of rows with white squares in the i-th column.
The first line of each block contains two integers r and c separated by a single space, 2 <= r <= c <= 1000. These are the numbers of rows and columns, respectively. Each of the next c lines in the block contains two integers separated by a single space. The integers in the input line i + 1 in the block, 1 <= i <= c, are labels of rows with white squares in the i-th column.
Output
For the i-th block, 1 <= i <= x, your program should write to the i-th line of the standard output either a sequence of c row labels (separated by single spaces) forming a correct volley of hits at white squares in consecutive columns 1, 2, ..., c, or one word NO if such a volley does not exists.
Sample Input
2 4 4 2 4 3 4 1 3 1 4 5 5 1 5 2 4 3 4 2 4 2 3
Sample Output
2 3 1 4 NO
Source
题目意思:
有n*m的格子,每个格子要么是白色要么是黑色。题目给定每列有2个白色的格子,其他的格子为黑色。每列选出一个白色的格子,使得每一行至少有一个白色格子被选出,若能满足条件则输出每列选出白色格子的行数,否则输出NO。
思路:
列标号放在左边,行标号放在右边,若该列a可选择第b行和第c行,则a-b连边,a-c连边。
在增广过程中记录to[i]和from[j]即第i列选择的行的标号和第j行被选择的列的标号。
init:to 0;from -1
1、若n>m,一定不可满足条件
2、若增广结束后存在from[i]=-1,则第i行一定不能被选择,输出NO
3、若增广结束后存在to[i]=0,那么第i列选择a和b其中一个即可。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 #include <queue> 7 #include <cmath> 8 #include <set> 9 using namespace std; 10 11 #define N 1005 12 #define inf 999999999 13 14 int max(int x,int y){return x>y?x:y;} 15 int min(int x,int y){return x<y?x:y;} 16 int abs(int x,int y){return x<0?-x:x;} 17 18 int from[N]; 19 int to[N]; 20 bool visited[N]; 21 int n, m; 22 vector<int>ve[N]; 23 24 int march(int u){ 25 int i, v; 26 for(i=0;i<ve[u].size();i++){ 27 v=ve[u][i]; 28 if(!visited[v]){ 29 visited[v]=true; 30 if(from[v]==-1||march(from[v])){ 31 from[v]=u; 32 to[u]=v; 33 return 1; 34 } 35 } 36 } 37 return 0; 38 } 39 40 main() 41 { 42 int t, i, j, k, u, v; 43 cin>>t; 44 while(t--){ 45 scanf("%d %d",&n,&m); 46 for(i=0;i<=m;i++) ve[i].clear(); 47 for(i=1;i<=m;i++){ 48 scanf("%d %d",&u,&v); 49 ve[i].push_back(u); 50 ve[i].push_back(v); 51 } 52 if(n>m) { 53 printf("NO\n");continue; 54 } 55 memset(from,-1,sizeof(from)); 56 int num=0; 57 for(i=1;i<=m;i++){ 58 memset(visited,false,sizeof(visited)); 59 march(i); 60 } 61 int f=1; 62 for(i=1;i<=n;i++){ 63 if(from[i]==-1){ 64 f=0;break; 65 } 66 } 67 if(!f){ 68 printf("NO\n");continue; 69 } 70 for(i=1;i<=m;i++){ 71 if(!to[i]){ 72 to[i]=ve[i][0]; 73 } 74 } 75 printf("%d",to[1]); 76 for(i=2;i<=m;i++) printf(" %d",to[i]); 77 cout<<endl; 78 } 79 }