POJ 1719 二分图最大匹配(记录路径)

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.

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

 
题目意思:
有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
");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
");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 }
原文地址:https://www.cnblogs.com/qq1012662902/p/4639005.html