Shooting Contest
Time Limit: 1000MS |
|
Memory Limit: 10000K |
Total Submissions: 2279 |
|
Accepted: 809 |
|
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.
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.
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
CEOI 1997
/* 一开始拿到这道题一下子就想到了二分图的最大匹配,然后想来想去没有把图的映射关系 想明白,就放弃二分了,转去想DP,但是想来想去也没有找到子结构关系,于是又转回二 分图。经过仔细分析终于找到了规律,首先如果列数少于行数是肯定要输出NO的,因为一 列只能覆盖一行,所以不能覆盖所有行。接下来就是建图了,以行为左,列为右建立二分 图,然后对二分图算最大匹配total,如果total < 行数则输出NO,否则依次遍历所有列并 输出其对应的行即pre,对于pre[i] != 0的就输出pre[i]否则,从i可以连的行中随便找一个输出 即可 */ #include <iostream> #define MAX_N 1000 using namespace std; bool v[MAX_N + 1]; int pre[MAX_N + 1]; int rowCol[MAX_N + 1][MAX_N + 1]; int colRow[MAX_N + 1]; int r, c; bool canGo(int from) { int num = rowCol[from][0]; int p, to; for(p = 1; p <= num; p++) { to = rowCol[from][p]; if(!v[to]) { v[to] = true; if(pre[to] == 0 || canGo(pre[to])) { pre[to] = from; return true; } } } return false; } int main() { int caseN, i; scanf("%d", &caseN); while(caseN--) { int row1, row2; memset(rowCol, 0, sizeof(rowCol)); scanf("%d%d", &r, &c); for(i = 1; i <= c; i++) { scanf("%d%d", &row1, &row2); rowCol[row1][0]++; rowCol[row1][rowCol[row1][0]] = i; colRow[i] = row1; rowCol[row2][0]++; rowCol[row2][rowCol[row2][0]] = i; } int total = 0; bool can = true; if(c < r) can = false; else { memset(pre, 0, sizeof(pre)); for(i = 1; i <= r; i++) { memset(v, 0, sizeof(v)); if(canGo(i)) total++; } if(total < r) can = false; } if(!can) printf("NO/n"); else { for(i = 1; i <= c; i++) { if(i != 1) printf(" "); if(pre[i] != 0) printf("%d", pre[i]); else printf("%d", colRow[i]); } printf("/n"); } } return 0; }