百度之星初赛二--度度熊与排列--二分匹配
作者:互联网
度度熊与排列
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_jaj=bj 且 ai<bia_i < b_iai<bi。
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 个字符串的输出结果。
-
1≤T≤1001 \le T \le 1001≤T≤100
-
1≤N≤201 \le N \le 201≤N≤20
-
1≤M≤501 \le M \le 501≤M≤50
-
字符串由英文小写字母('a' 至 'z') 组成
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