CF 467D Strongly Connected Component Condensed Point DP

After shrinking the points, do DP on the DAG in topological order.
Note that SUMLEN may explode INT.

#include <bits/stdc++.h>
using namespace std;
map<string,int>mp;
int tot=0;
int n,m;
string s[200003];
struct edge{
    int to,next;
}e[200003];
int head[200003];
int dfn[200003];
int low[200003];
int stk[200003];
bool instk[200003];
int scc[200003];
int rcnt[200003];
int len[200003];
int srcnt[200003];
int slen[200003];
int ind[200003];
vector<int>rg[200003];
int cnt,tmpdfn,scc_cnt,top;
void add(int u,int v){
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void init(){
    cnt=tmpdfn=scc_cnt=top=0;
    memset(head,-1,sizeof(head));
    memset(dfn,0,sizeof(dfn));
}
void pro(string a){
    int rc=0;
    for(int i=0;a[i];i++){
        if(a[i]>='A'&&a[i]<='Z')a[i]+='a'-'A';
        if(a[i]=='r')rc++;
    }
    if(mp.find(a)==mp.end())mp[a]=++tot;
    int id=mp[a];
    rcnt[id]=rc;
    len[id]=a.length();
}
void dfs(int u){
    dfn[u]=++tmpdfn;
    low[u]=dfn[u];
    stk[++top]=u;
    instk[u]=true;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(!dfn[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instk[v])low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u]){
        ++scc_cnt;
        srcnt[scc_cnt]=rcnt[u];
        slen[scc_cnt]=len[u];
        while(1){
            int x=stk[top--];
            instk[x]=false;
            scc[x]=scc_cnt;
            if(srcnt[scc_cnt]>rcnt[x]){
                srcnt[scc_cnt]=rcnt[x];
                slen[scc_cnt]=len[x];
            }
            else if(srcnt[scc_cnt]==rcnt[x]&&slen[scc_cnt]>len[x]){
                slen[scc_cnt]=len[x];
            }
            if(x==u)break;
        }
    }
}

queue<int>q;

int main(){
    init();
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        cin>>s[i];
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        string a,b;
        cin>>a>>b;
        pro(a);
        pro(b);
        for(int i=0;a[i];i++){
            if(a[i]>='A'&&a[i]<='Z')a[i]+='a'-'A';
        }
        for(int i=0;b[i];i++){
            if(b[i]>='A'&&b[i]<='Z')b[i]+='a'-'A';
        }
        int ida=mp[a],idb=mp[b];
        add(ida,idb);
    }
    for(int i=1;i<=tot;i++){
        if(!dfn[i])dfs(i);
    }
    for(int u=1;u<=tot;u++){
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].to;
            if(scc[u]==scc[v])continue;
            ind[scc[u]]++;
            rg[scc[v]].push_back(scc[u]);
        }
    }
    for(int i=1;i<=scc_cnt;i++)if(ind[i]==0)q.push(i);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=0;i<rg[u].size();i++){
            int v=rg[u][i];
            if(srcnt[v]>srcnt[u]){
                srcnt[v]=srcnt[u];
                slen[v]=slen[u];
            }
            else if(srcnt[v]==srcnt[u]&&slen[v]>slen[u]){
                slen[v]=slen[u];
            }
            ind[v]--;
            if(ind[v]==0)q.push(v);
        }
    }
    int sumr=0;
    long long sumlen=0;
    for(int i=1;i<=n;i++){
        int tmpr=0,tmplen=s[i].length();
        for(int j=0;s[i][j];j++){
            if(s[i][j]>='A'&&s[i][j]<='Z')s[i][j]+='a'-'A';
            if(s[i][j]=='r')tmpr++;
        }
        if(mp.find(s[i])==mp.end()){
            sumr+=tmpr;
            sumlen+=tmplen;
        }
        else {
            int id=mp[s[i]];
            id=scc[id];
            sumr+=srcnt[id];
            sumlen+=slen[id];
        }
    }
    printf("%d %lld\n",sumr,sumlen);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325945842&siteId=291194637