sgu264:Travel(稳定婚姻问题)

题目大意:
       n 个男人和n个女人,每个男人都在心中有对 n 个女人的喜欢程度,每个女人亦然。求出一种完备匹配的方案使得任意一对男女(除去匹配的 n ),满足这对男女之间的喜欢程度不都大于喜欢自己配对对象的程度。

分析:
       学习了稳定婚姻问题,大概就是男的依次和女的约会,能约得上就配对,能优于女的原来的配偶也能配对,不行就下一个女的。
       ( 感觉好扯的算法,但很容易证明其正确性)

       BTW. 注意输入啥的要用 gets 就好了。

AC code:

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#define pb push_back
#define mp make_pair

#define debug(...) fprintf(stderr, __VA_ARGS__)
#include <ctime>

typedef long long LL;
typedef double DB;
typedef long double LD;
using namespace std;

const int MAXN = 809;
const int MAXL = 12;

int n;
char input[MAXN*MAXL];
char output[MAXL*2];
char p1[MAXN][MAXN][MAXL];
char p2[MAXN][MAXN][MAXL];
int g1[MAXN][MAXN], g2[MAXN][MAXN];
int mat[MAXN];
map<string,int> num1, num2;
char name1[MAXN][MAXL], name2[MAXN][MAXL];
queue<int> q;
int id[MAXN];

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif

    scanf("%d\n", &n);
    for(int i = 1; i <= n; ++i)
    {
        gets(input);
        input[strlen(input)] = '\n';
        int j = 0, k;
        for(k = 0; input[j] != ' ' && input[j] != '\n'; ++j, ++k)
            name1[i][k] = input[j];
        num1[name1[i]] = i;
        for(int t = 1; t <= n; ++t)
        {
            for(++j, k = 0; input[j] != ' ' && input[j] != '\n'; ++j, ++k)
                p1[i][t][k] = input[j];
        }
    }
    for(int i = 1; i <= n; ++i)
    {
        gets(input);
        input[strlen(input)] = '\n';
        int j = 0, k;
        for(k = 0; input[j] != ' ' && input[j] != '\n'; ++j, ++k)
            name2[i][k] = input[j];
        num2[name2[i]] = i;
        for(int t = 1; t <= n; ++t)
        {
            for(++j, k = 0; input[j] != ' ' && input[j] != '\n'; ++j, ++k)
                p2[i][t][k] = input[j];
        }
    }

    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
        {
            g1[i][j] = num2[p1[i][j]];
            g2[i][num1[p2[i][j]]] = j;
        }
    for(int i = 1; i <= n; ++i)
        q.push(i), id[i] = 1;
    while(!q.empty())
    {
        int now = q.front();q.pop();
        int best = g1[now][id[now]++];
        if(!mat[best])
            mat[best] = now;
        else
        {
            if(g2[best][mat[best]] < g2[best][now])
                q.push(now);
            else
            {
                q.push(mat[best]);
                mat[best] = now;
            }
        }
    }
    puts("YES");
    for(int i = 1; i <= n; ++i)
    {
        memset(output, 0, sizeof output);
        strcpy(output, name1[mat[i]]);
        output[strlen(output)] = ' ';
        strcpy(output+strlen(output), name2[i]);
        puts(output);
    }

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值