【百度之星】度度熊与排列【暴力+二分图匹配】
题意:中文题,题意很好懂。要求每两个字符串重排以后编号要一样,可能有多种情况,就找字典序就小的。
题解:一开始有点懵,然后发现要找的序列要满足所以字符串,不知所措。然后想到了那么多人过了,肯定暴力啊。然后就暴力二分图匹配,找到满足情况的i,j匹配起来。然后跑一个匈牙利,倒着跑(字典序最小)。然后就能得到结果啦。注意跑完以后还要看看匹配数量和link的值哦。
#pragma comment(linker, "/STACK:102400000,102400000") #pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<queue> #include<set> #include<cmath> #include<string> #include<map> #include<vector> #include<ctime> #include<stack> using namespace std; #define mm(a,b) memset(a,b,sizeof(a)) typedef long long ll; map<long long,bool> M; const long long mod=1234577; const int maxn=1e6+10; ll gcd(ll x, ll y) {if (y == 0) return x; else return gcd(y, x % y); } const double eps=1e-8; int k; int g[600][600]; int link[600]; bool used[500]; int n,m; bool dfs(int u) { int v; for(v=1;v<=m;v++) if(g[u][v]&&!used[v]) { used[v]=true; if(link[v]==-1||dfs(link[v])) { link[v]=u; return true; } } return false; } int hungary() { int res=0; int u; memset(link,-1,sizeof(link)); for(u=m;u>=1;u--) { memset(used,0,sizeof(used)); if(dfs(u)) res++; } return res; } int main() { int T; scanf("%d",&T); while(T--) { mm(g,0); string N[25]; scanf("%d %d",&n,&m); char s1[30][55],s2[30][55]; for(int c=0;c<n;c++) { scanf("%s",s1[c]); scanf("%s",s2[c]); } for(int i=0;i<m;i++) { for(int j=0;j<m;j++) { int flag=1; for(int k=0;k<n;k++) { if(s1[k][i]!=s2[k][j]) { flag=0; break; } } if(flag) g[j+1][i+1]=1; } } int ans=hungary(); //printf("%d\n",ans); int flag=1; for(int i=1;i<=m;i++) { if(link[i]==-1) { flag=0; break; } } if(!flag) { printf("-1\n"); continue; } for(int i=1;i<=m;i++) { printf("%d",link[i]); if(i!=m) printf(" "); } printf("\n"); } return 0; }