UVALive 5963 (LA 5963) Confusion in the Problem Set 二分图匹配 (或 YY)

题目大意:

对于给定的一个数列 a[n] 如果能找到 a[n] 的一种排列使得每个对于位置 i 的数 a[i] 满足 a[i] = i - 1 或者 a[i] = n - 1则输出"yes", 否则输出“no"


大致思路:

将左边和右边都分 n 个点, 代表左边(输入的a[i]的排列)

首先对于左边每个位置 i 的a[i] 与右边(可能的最终排列)的n个点连边

对于左边的点 k 与右边的编号分别 a[k] + 1 和 n - a[k] 的点连边然后寻找最大匹配,直接用匈牙利算法即可

如果最大匹配数是n就输出 yes 否则输出 no

代码如下:

Result  :  Accepted     Memory  :  0 KB     Time  :  109 ms

/*
 * Author: Gatevin
 * Created Time:  2014/8/3 14:09:34
 * File Name: test.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

int t;
int n;
int a[10010];

const int maxn = 10010;

vector <int> g[maxn];
int from[maxn], tot;
bool use[maxn];

bool match(int x)
{
    for(int i = 0; i < g[x].size(); i++)
    {
        if(!use[g[x][i]])
        {
            use[g[x][i]] = true;
            if(from[g[x][i]] == -1 || match(from[g[x][i]]))
            {
                from[g[x][i]] = x;
                return true;
            }
        }
    }
    return false;
}

int hungary()
{
    tot = 0;
    memset(from, 255, sizeof(from));
    for(int i = 1; i <= n; i++)
    {
        memset(use, 0, sizeof(use));
        if(match(i))
            ++tot;
    }
    return tot;
}

int main()
{
    scanf("%d",&t);
    bool flag = false;
    for(int cas = 1; cas <= t; cas++)
    {
        scanf("%d",&n);
        flag = false;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
            if(a[i] >= n)
            {
                flag = true;
            }
            g[i].push_back(a[i] + 1);
            g[i].push_back(n - a[i]);
        }
        if(flag)
        {
            printf("Case %d: no\n",cas);
            for(int i = 1; i <= n; i++)
            {
              if(!g[i].empty())
               {
                   g[i].clear();
               }
             }
            continue;
        }
        int ans = hungary();
        if(ans == n)
        {
            printf("Case %d: yes\n",cas);
        }
        else
        {
            printf("Case %d: no\n",cas);
        }
        for(int i = 1; i <= n; i++)
        {
            if(!g[i].empty())
            {
                g[i].clear();
            }
        }
    }
    return 0;
}

当然还可以用YY的做法

对于右边每个点,用b[n]表示其可以与左边的点匹配的数量, 如果所有的右边的点可以与左边的点的匹配数量都是2就输出”yes",否则输出 “no"

cyl这个YY帝的做法:

Result  :  Accepted     Memory  :  0 KB     Time  :  36 ms

/*
 *	Author:
 *		Indestinee
 * 	Date:
 *	  	2014.08.03 
 */ 
 
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define ll long long
#define cls(a) memset(a,0,sizeof(a))
#define rise(i,a,b) for(i=a;i<=b;i++)
#define fall(i,a,b) for(i=a;i>=b;i--)
int cas, T, i, n, a, cnt[10001];
bool flag;
int main()
{
	cin >> cas;
	rise( T , 1 , cas )
	{
		flag = true;
		cin >> n;
		cls( cnt );
		rise( i , 1 , n ) 
		{
			scanf( "%d" , &a );
			cnt[min(a,(n-1-a))] ++;
		}
		fall( i , ( n - 1 ) / 2 - 1 , 0 ) if( cnt[i] != 2 ) 
		{
			flag = false;
			break;  
		}
		if( n % 2 && cnt[n/2] != 1 ) flag = false;
		if( n % 2 == 0 && cnt[n/2-1] != 2 ) flag = false; 
		cout << "Case " << T << ": ";
		if( !flag ) cout << "no" << endl;
		else cout << "yes" << endl;
	} 
	return 0;
}


你可能感兴趣的:(uvalive,YY,二分图匹配,5963,LA5963)