标签:check let sum code 字母 pos highlight std ret
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1009G.html
给定一个长度为 $n$ 的字符串 $s$ 。并给定 $m$ 条限制,第 $i$ 条限制声明了第 $i$ 个位置的字符可以取的值。如果没有声明表示可以任意取值。
求一个字符串 $s$ 的排列,在满足 $m$ 条限制的同时,使得字典序最小。如果不存在满足限制条件的字符串,则输出 $-1$。
$n,m\leq 10^5$,字符集 $ = {‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘}$
我们先考虑如何判定是否有解。
统计一下原字符串中每一个字母的出现次数。容易建出一个二分图,左侧的 $n$ 个节点为字符串的每一个位置,右侧的 $n$ 个节点为 $n$ 个字母,这 $n$ 个字母中每种字符的出现次数等于原字符串中对应字符的出现次数;对于左侧的每一个点,即字符串的每一个位置,向它所能填的字母连上边(补充一下:这样做,右侧相同字母节点其实是等价的)。那么,只需要求出最大匹配数,就可以知道最多有多少个位置可以放正确的字母。
然而,我们是否可以得到一种较快的判定是否有完美匹配的做法呢?显然有啊。
霍尔定理:设一个二分图 G 中的两部分顶点组成的集合分别为 X, Y ,则 G 中有一组无公共点的边,一端恰好为组成X的点的充分必要条件是:X中的任意k个点至少与Y中的k个点相邻。
根据霍尔定理,得到:
命题1 :一个满足 |X| = |Y| 的二分图,存在完美匹配的充分必要条件是:在 X 中任选 k 个点,至少与 y 中 k 个点相邻;在 Y 中任选 k 个点,至少与 x 中 k 个点相邻。
回到原图。
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int read(){
int x=0;
char ch=getchar();
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
char s[N];
int n,v[N],suf[N][64],tot[64],sum[64],Log[64];
void getv(){
int m=read();
memset(v,0,sizeof v);
while (m--){
int id=read();
char s[10];
scanf("%s",s+1);
int len=strlen(s+1);
for (int i=1;i<=len;i++)
v[id]|=1<<(s[i]-‘a‘);
}
for (int i=1;i<=n;i++)
if (v[i]==0)
v[i]=63;
}
bool check(int p){
sum[0]=0;
for (int i=1;i<64;i++){
sum[i]=sum[i^(i&-i)]+tot[i&-i];
if (sum[i]<suf[p][i])
return 0;
}
return 1;
}
int main(){
Log[1]=0;
for (int i=2;i<64;i++)
Log[i]=Log[i>>1]+1;
gets(s+1);
n=strlen(s+1);
getv();
memset(tot,0,sizeof tot);
for (int i=1;i<=n;i++)
tot[1<<(s[i]-‘a‘)]++;
memset(suf,0,sizeof suf);
for (int i=n;i>=1;i--){
for (int j=0;j<64;j++)
suf[i][j]=suf[i+1][j];
suf[i][v[i]]++;
}
for (int id=1;id<=n;id++)
for (int i=1;i<64;i<<=1)
for (int j=0;j<64;j++)
if (j&i)
suf[id][j]+=suf[id][j^i];
if (!check(1)){
printf("Impossible");
return 0;
}
for (int i=1;i<=n;i++)
for (int j=v[i],k=j&-j;j;j^=k,k=j&-j){
tot[k]--;
if (check(i+1)){
putchar(‘a‘+Log[k]);
break;
}
tot[k]++;
}
return 0;
}
Codeforces 1009G Allowed Letters FMT,二分图,二分图匹配,霍尔定理
标签:check let sum code 字母 pos highlight std ret
原文地址:https://www.cnblogs.com/zhouzhendong/p/CF1009G.html