USACO Ag T1 求 Hack
  • 板块学术版
  • 楼主__vector__
  • 当前回复4
  • 已保存回复4
  • 发布时间2023/1/31 23:02
  • 上次更新2023/10/24 02:18:00
查看原帖
USACO Ag T1 求 Hack
507348
__vector__楼主2023/1/31 23:02

RT.
赛时 T1,T2 都尝试写正解,都 WA 了,Gold 无望。

以下来自我的游记

读了一遍题,发现原题面可以用一个有向图表示出来。  
我认为一种字母变为另一种字母,就是建一条有向边。  
如果某个点出度 $\ge 2$,或者所有连通子图都是环且所有字母都出现过,无解。  
我手动模拟了一些数据,发现对于每个连通子图,如果是链,对答案的贡献为 size,如果是环,则还有破环为链的代价,贡献为 size+1。   

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int t;
char a[maxn],b[maxn];
map<char,char> to;
map<char,bool> ins;
map<char,int> siz;
map<char,bool> vis;
bool circle=0;
void dfs(char u)
{
    if(vis[u])
    {
        siz[u]=0;
        return;
    }
    vis[u]=1;
    ins[u]=1;
    if(to[u]&&to[u]!=u)
    {
        siz[u]=1;
        if(ins[to[u]])
        {
            ins[u]=0;
            circle=1;
            return;
        }
        dfs(to[u]);
    }
    ins[u]=0;
    siz[u]+=siz[to[u]];
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        ins.clear();
        to.clear();
        siz.clear();
        vis.clear();
        scanf("%s",a+1);
        scanf("%s",b+1);
        int n=strlen(a+1);
        assert(n==strlen(b+1));
        bool imposs=0;
        for(int i=1;i<=n;i++)
        {
            if(!to[a[i]])
            {
                to[a[i]]=b[i];
            }
            else if(to[a[i]])
            {     
                if(to[a[i]]!=b[i])
                {
                    imposs=1;
                    break;
                }
            }  
        }
        if(imposs)
        {
            puts("-1");
            continue;
        }
        bool hasd0=0;//存在可以变成空闲的点
        for(char i='a';i<='z';i++)
        {
            circle=0;
            dfs(i);
            if(!circle)
            {
                hasd0=1;
                break;
            }
        }
        for(char i='A';i<='Z';i++)
        {// 接着上一个循环枚举
            circle=0;
            dfs(i);
            if(!circle)
            {
                hasd0=1;
                break;
            }
        }
        //==================
        ins.clear();
        siz.clear();
        vis.clear();
        int ans=0;
        for(char i='a';i<='z';i++)
        {
            if(!to[i]||(i==to[i]||vis[i]))continue;
            circle=0;
            dfs(i);
            if(!circle)
            {
          //      printf("(1) char: %c added: %d\n",i,siz[i]);
                ans+=siz[i];
            }
            else if(circle)
            {
        //        printf("(2) char: %c added: %d\n",i,siz[i]+1);
                ans+=siz[i]+1;
                if(!hasd0)
                {
                    imposs=1;
                    break;
                }
            }
        }
        for(char i='A';i<='Z';i++)
        {// 接着上一个循环枚举
            if(!to[i]||(i==to[i]||vis[i]))continue;
            circle=0;
            dfs(i);
            if(!circle)
            {
         //       printf("(1) char: %c added: %d\n",i,siz[i]);
                ans+=siz[i];
            }
            else if(circle)
            {
            //    printf("(2) char: %c added: %d\n",i,siz[i]+1);
                ans+=siz[i]+1;
                if(!hasd0)
                {
                    imposs=1;
                    break;
                }
            }
        }
        if(imposs)puts("-1");
        else printf("%d\n",ans);
    }
    return 0;
}  
2023/1/31 23:02
加载中...