• 团结就是力量(tarjan+字符串hash)-牛客


    团结就是力量(tarjan+字符串hash)-牛客

    题意:给定n个字符串,和m对信息构成图,字符串经过变换后完全相等+两个点互相连通,可以一起出站,团结力:一起出站的最大人数

    解:tarjan求最大连通分量,先将字符串预处理为字典序最小(字符串同构最小表示法),最后离散化求最大值(连块+核对字符)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    const int mod=142857;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    typedef pair<int,int> pii;
    
    string getmin(string s)
    {
        int len=s.length();
        s+=s;
    
        int i=0,j=1,k=0,t;
        while(i<len&&j<len&&k<len)
        {
            t=s[(i+k)%len]-s[(j+k)%len];
            if(t==0) k++;
            else
            {
                if(t>0) i+=k+1;
                else j+=k+1;
                if(i==j) j++;
                k=0;
            }
        }
        string res=s.substr(min(i,j),len);
        return res;
    }
    
    //强连通缩点
    int dfn[maxn],low[maxn],tot;
    int Stack[maxn],vis[maxn],idx;
    int cnt;//连通分量的个数
    int belong[maxn];//记录每个节点的强连通编号
    
    vector<int> G[maxn*2];
    string str[maxn];
    int n,m,ans;
    
    void tarjan(int u)
    {
        dfn[u]=low[u]=++tot;
        vis[u]=1;
        Stack[++idx]=u;
        for(auto v:G[u])
        {
            if(!dfn[v])
            {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v])
            {
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u])
        {
            cnt++;
            int k;
            map<string ,int> mp;
            do
            {
                k=Stack[idx--];
                mp[str[k]]++;//对连通分量计数
                vis[k]=0;
            }while(k!=u);
    
            for(auto it:mp)
             ans=max(ans,it.second);
        }
    }
    int main()
    {
        while(cin>>n>>m)
        {
            for(int i=1; i<=n; i++)
             G[i].clear(),dfn[i]=low[i]=vis[i]=0;
            tot=cnt=0;
            idx=ans=0;
            for(int i=1; i<=n; i++)
             {
                 cin>>str[i];
                 str[i]=getmin(str[i]);
                 //cout<<str[i]<<endl;
             }
            for(int i=0; i<m; i++)
             {
               int u,v;
               cin>>u>>v;
              G[u].push_back(v);
             }
            for(int i=1; i<=n; i++)
             {
              if(!dfn[i])
               tarjan(i);
             }
            printf("%d
    ",ans);
        }
        system("pause");
        return 0;
    }
  • 相关阅读:
    android.mk 文件中变量
    【转】An Intuitive Guide To Exponential Functions & e
    卷积相关
    opencv 调试时不显示图像
    Luhn 算法-- 信用卡号码的校验
    perl 脚本实现简单搜索修改文件并生成diff文件
    【转】gcc: multiple definition of [转]
    【转】undefined reference问题总结
    【转】pthread_cond_t怎么使用
    linux编程使用记录
  • 原文地址:https://www.cnblogs.com/sweetlittlebaby/p/13460509.html
Copyright © 2020-2023  润新知