http://wikioi.com/problem/1222/
一开始我就想到这样构图的,即可能的连边。但是似乎无法判断。
然后想来想去想不出来。。
题解:
同样是二分图,将可能的连边,然后跑一次最大匹配,如果能完美匹配,那么就可能有肯定的信与信封,否则输出none,这点是显然的。
然后我们来考虑如何找出肯定的。
那么一定是在最大匹配的基础上,假设我们删了一个匹配(u, v),u却能匹配(即还是完美匹配),说明u肯定不是一个答案。因为它不唯一
反之如果不能完美匹配,说明他就是一个答案。
在标记的时候记得标记回来(一开始我觉得写lx是多余的,但是后来发现,,答案要求是按信有序,,所以,你懂的。。)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
#define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }
const int N=105;
bool del[N][N], vis[N];
int ly[N], lx[N], n;
const bool ifind(const int &x) {
for1(y, 1, n) if(!del[x][y] && !vis[y]) {
vis[y]=1;
if(!ly[y] || ifind(ly[y])) {
lx[x]=y;
ly[y]=x;
return true;
}
}
return false;
}
int main() {
read(n);
int u, v, ans=0, flag=1;
for(u=getint(), v=getint(); u&&v; u=getint(), v=getint()) del[u][v]=1;
for1(i, 1, n) {
CC(vis, 0);
if(ifind(i)) ++ans;
}
if(ans!=n) puts("none");
else {
for1(i, 1, n) {
v=lx[i];
del[i][v]=1;
ly[v]=0;
CC(vis, 0);
if(!ifind(i)) {
printf("%d %d\n", i, v);
flag=0; ly[v]=i;
}
del[i][v]=0;
}
if(flag) puts("none");
}
return 0;
}
题目描述 Description
John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出。但是,第二天John的儿子Small John将这n封信都拿出了信封。不幸的是,Small John无法将拿出的信正确地装回信封中了。
将Small John所提供的n封信依次编号为1,2,…,n;且n个信封也依次编号为1,2,…,n。假定Small John能提供一组信息:第i封信肯定不是装在信封j中。请编程帮助Small John,尽可能多地将信正确地装回信封。
输入描述 Input Description
n文件的第一行是一个整数n(n≤100)。信和信封依次编号为1,2,…,n。
n接下来的各行中每行有2个数i和j,表示第i封信肯定不是装在第j个信封中。文件最后一行是2个0,表示结束。
输出描述 Output Description
输出文件的各行中每行有2个数i和j,表示第i封信肯定是装在第j个信封中。请按信的编号i从小到大顺序输出。若不能确定正确装入信封的任何信件,则输出“none”。
样例输入 Sample Input
3
1 2
1 3
2 1
0 0
样例输出 Sample Output
1 1