您的位置:首页 > 大数据 > 人工智能

2017 Multi-University Training Contest - Team 1 1006 【思维+强联通找环】

2017-07-27 11:02 417 查看
传送门

//这道题真的好, 结合了联通分量和置换群和查分约束的思想, 我还是太菜了啊, 想不到啊.

//题意就是给你一个方程, f(i)=bf(ai) , i 从给所给的序列中依次赋值, 问共有多少中方式使得这个方程成立.

第一分样例可以解释为:

110

111

001

000

思路:实际上就是从a集合到b集合的映射的组合,a中的一个循环节是一个整体,如果b中循环节的长度和a循环节的长度相同或者是因子,那么就可以置换过来,满足这个条件,将结果组合一下就好. 所以关键就是找出每一个环, 且把两个序列中的环都要找出, 并求出环的长度, 也就是找循环节和循环节法因子, 然后把结果乘起来就是了.

//找环不一定用强联通来找, 也可以暴力.

AC Code

/** @Cain*/
const int maxn=1e5+5;
int cas=1;
int bel[maxn],low[maxn],dfn[maxn];
vector<int >G[maxn];
stack<int > S;
int cnt ,res;
int cur;
int numA[maxn],numB[maxn];
int a[maxn],b[maxn];
void init(int n)
{
Fill(low,0);
Fill(dfn,0);
Fill(bel,0);
for(int i=1;i<=n;i++)
G[i].clear();
cnt = 1; res = 0;
}

void tarjan(int u)   //强联通找环.
{
dfn[u] = low[u] = cnt++;
S.push(u);
for(int i=0;i<G[u].size();i++){
int v = G[u][i];
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(!bel[v])
low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u]){
res++;
while(1){
int v = S.top();
S.pop();
bel[v] = res;
if(u == v ) break;
}
}
}

void solve()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
Fill(numA,0); Fill(numB,0);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]++;
}
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
b[i]++;
}
init(n);
for(int i=1;i<=n;i++){
G[a[i]].push_back(i);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i);
}
cur = res;
for(int i=1;i<=n;i++){
numA[bel[i]]++;
}
//A环找完
init(m);
for(int i=1;i<=m;i++){
G[b[i]].push_back(i);
}
for(int i=1;i<=m;i++){
if(!dfn[i]) tarjan(i);
}
for(int i=1;i<=m;i++){
numB[bel[i]]++;
}
int s[maxn] = {0};
for(int i=1;i<=m;i++){
s[numB[i]] += numB[i];
}
//B环找完.
ll ans[maxn] = {0};
for(int i=1;i<=cur;i++){   //循环节.
for(int j=1;j<=sqrt(numA[i]);j++){   //循环节因子.
if(numA[i] % j == 0){
ans[i] += s[j];
if(numA[i] / j != j)
ans[i] += s[numA[i] / j];
}
}
}

printf("Case #%d: ",cas++);
ll xx = ans[1];
for(int i=2;i<=cur;i++){
xx *= ans[i];
xx %= mod;
}
printf("%lld\n",xx);
}
}

int main()
{
int t = 1 ;
//scanf("%d",&t);
while(t--){
//    printf("Case %d: ", cas++);
solve();
//printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐