• 【wikioi】1222 信与信封问题(二分图+特殊的技巧)


    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
    ", 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

    数据范围及提示 Data Size & Hint

  • 相关阅读:
    Spring AOP
    TestNG配合ant脚本进行单元测试
    TestNG配合catubuter统计单元测试的代码覆盖率
    junit配合catubuter统计单元测试的代码覆盖率
    TestNG离线安装步骤
    spring 整合redis集群中使用@autowire无效问题的解决办法
    @Repository、@Service、@Controller 和 @Component
    用VMware克隆CentOS 6.5如何进行网络设置
    centos 6.5 dhcp桥接方式上网络设置
    centos 6.5 关闭防火墙
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3944957.html
Copyright © 2020-2023  润新知