其他分享
首页 > 其他分享> > 百度之星初赛二--度度熊与排列--二分匹配

百度之星初赛二--度度熊与排列--二分匹配

作者:互联网

度度熊与排列

Accepts: 1100

Submissions: 3486

Time Limit: 2000/1000 MS (Java/Others)

Memory Limit: 32768/32768 K (Java/Others)

Problem Description

度熊有一个机器,这个机器有一个 1∼M1 \sim M1∼M 的排列 p[1..M]p[1..M]p[1..M] 当作参数,若丢进一个长度为 MMM 的字符串,此机器会将此字符串重新排列后再输出,重新排列的方式为:原本第 iii 个位置的字符会变到第 p[i]p[i]p[i] 个位置。

举例来说,当 M=3M = 3M=3,p[1]=3,p[2]=1,p[3]=2p[1]=3,p[2]=1,p[3]=2p[1]=3,p[2]=1,p[3]=2,那么丢 "abc" 进入这个机器后,机器会输出"bca";若丢进的是 "ded",那么机器会输出 "edd"。

某天,度熊不小心忘记这个机器的参数了,只记得参数的长度是 MMM,于是他丢了 NNN 长度为 MMM 的字符串进去,并记录下对于每个字符串机器的输出结果,请你根据这些结果,帮度熊找回这个机器的参数。若有多组参数都满足度熊的记录,请输出字典序最小的排列作为参数。若并不存在任何参数满足度熊的记录,请输出 −1-1−1。

注:对于两个相异的排列a: a[1..M]a[1..M]a[1..M] 和 b[1..M]b[1..M]b[1..M],我们称 aaa 比 bbb 小当且仅当 存在一个 iii,满足对于所有小于 iii 的 jjj 都有 aj=bja_j = b_ja​j​​=b​j​​ 且 ai<bia_i < b_ia​i​​<b​i​​。

Input

有多组询问,第一行包含一个正整数 TTT 代表有几组询问。

每组询问的第一行包含两个正整数 N,MN, MN,M,分别代表度熊丢进机器的字符串数目以及参数的长度。接下来还有 2×N2 \times N2×N 行,每行有一个长度为 MMM 的字符串,当中的第 2×i−12 \times i - 12×i−1 行的字符串代表度熊丢进去机器的第 iii 个字符串,而第 2×i2 \times i2×i 行的字符串代表机器对于第 iii 个字符串的输出结果。

Output

对于每一个询问,输出一行,若不存在任何参数满足度熊的记录,这行只包含一个整数 −1-1−1。否则这行包含一个排列,代表此机器所有可能的参数中字典序最小的那个。

Sample Input

Copy

4
1 3
abc
bca
2 4
aaab
baaa
cdcc
cccd
3 3
aaa
aaa
bbb
bbb
ccc
ccc
1 1
a
z

Sample Output

Copy

3 1 2
2 4 3 1
1 2 3
-1

Note
第一组询问中, p[1]=3,p[2]=1,p[3]=2p[1]=3,p[2]=1,p[3]=2p[1]=3,p[2]=1,p[3]=2 是唯一的机器可能的参数。

第二组询问中, p=[2,4,3,1]p=[2,4,3,1]p=[2,4,3,1] 和 p=[3,4,2,1]p=[3,4,2,1]p=[3,4,2,1] 都是机器可能的参数,不过 [2,4,3,1][2,4,3,1][2,4,3,1] 的字典序比 [3,4,2,1][3,4,2,1][3,4,2,1] 还小,故必须输出 2,4,3,1。 

就是二分图匹配。如果当前if(ch1[j]==ch2[k])  num[j][k]++; 如果num[j][k]为n,则加入边,然后跑二分匹配。

要注意是从后往前写,这样可以保证字典序最小。

#include <algorithm>    //STL通用算法
#include <bitset>     //STL位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>     //复数类
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>      //STL双端队列容器
#include <exception>    //异常处理类
#include <fstream>
#include <functional>   //STL定义运算函数(代替运算符)
#include <limits>
#include <list>      //STL线性列表容器
#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>      //基本输入/输出支持
#include<iosfwd>     //输入/输出系统使用的前置声明
#include <iostream>
#include <istream>     //基本输入流
#include <ostream>     //基本输出流
#include <queue>      //STL队列容器
#include <set>       //STL 集合容器
#include <sstream>    //基于字符串的流
#include <stack>      //STL堆栈容器    
#include <stdexcept>    //标准异常类
#include <streambuf>   //底层输入/输出支持
#include <string>     //字符串类
#include <utility>     //STL通用模板类
#include <vector>     //STL动态数组容器
#include <cwchar>
#include <cwctype>
#define ll long long
using namespace std;
//priority_queue<int,vector<int>,less<int> >q;
int dx[]= {-1,1,0,0,-1,-1,1,1};
int dy[]= {0,0,-1,1,-1,1,1,-1};
const int maxn = 1000+66;
const ll mod=1e9+7;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,m;
int vis[maxn];
int pre[maxn];
int ans[maxn];
int num[maxn][maxn];
int mark[maxn][maxn];
bool finds(int x)
{
    for(int i=1; i<=m; i++)
    {
        if(mark[x][i]&&!vis[i])
        {
            vis[i]=1;
            if(pre[i]==0||finds(pre[i]))
            {
                pre[i]=x;
                ans[x]=i;
                return 1;
            }
        }
    }
    return 0;
}
char ch1[maxn];
char ch2[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(num,0,sizeof(num));
        memset(pre,0,sizeof(pre));
        memset(mark,0,sizeof(mark));
        scanf("%d %d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            scanf("%s%s",ch1,ch2);
            for(int j=0; j<m; j++)
            {
                for(int k=0; k<m; k++)
                {
                    if(ch1[j]==ch2[k])
                        num[j][k]++;
                }
            }
        }
        for(int i=0; i<m; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(num[i][j]==n)
                    mark[i+1][j+1]=1;
            }
        }
        int sum=0;
        for(int i=m; i>=1; i--)
        {
            memset(vis,0,sizeof(vis));
            if(finds(i))
                sum++;
        }
        if(sum<m)
        {
            printf("-1\n");
        }
        else
        {
            for(int i=1; i<=m; i++)
            {
                printf("%d%c",ans[i],i==m?'\n':' ');
            }
        }
    }
}

 

标签:二分,机器,..,int,初赛,STL,度度,字符串,include
来源: https://blog.csdn.net/lanshan1111/article/details/99715515