• Luogu P2194 HXY烧情侣


    省选前颓几道水题?

    言归正传:
    显然这是一道TARJAN,题面已经想方设法在提醒你了

    这里还有一道双倍经验,稍微改一丢丢就可以了

    只要记录每个强联通分量中的最小元素值和最小元素值对应的数量即可

    看到很多题解都是全部处理完之后在最后统计最小元素值和最小元素对应数量并统计两个答案的,其实对于减小常数来说这样是没必要的,因为每个强连通分量只会在tarjan的途中被搜索到一次(可以叫做无后效性?)所以只要一边tarjan一边统计答案即可

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #define writep(x) write(x),putchar(' ')
    #define writeln(x) write(x),puts("") 
    #define ha 1000000007//珍惜生命,暴力取膜不可取,所以,我们取ha
    using namespace std;
    inline int read(){
        int ans=0,f=1;char chr=getchar();
        while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
        while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
        return ans*f;
    }void write(int x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
    }const int M=3e5+5;
    int n,m,a[M],head[M],ver[M],nxt[M],tot,dfn[M],low[M],ins[M],sta[M],top,t,mn[M],col,color[M],cnt[M],mc[M],ans1,ans2=1;
    /*
    col 强连通分量数量
    color[]强连通分量的编号
    cnt[]强连通分量重元素个数(这里貌似没用)
    mn[]强连通分量中值最小值
    mc[]强连通分量中最小值个数
    */
    inline void add(int x,int y){ver[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
    inline void cmin(int &a,int b){if(a>b) a=b;}
    void Tarjan(int x){
        dfn[x]=low[x]=++t;ins[x]=1,sta[top++]=x;
        for(register int i=head[x];i;i=nxt[i])
            if(ins[ver[i]]==0) Tarjan(ver[i]),cmin(low[x],low[ver[i]]);
            else if(ins[ver[i]]==1) cmin(low[x],dfn[ver[i]]);
        if(dfn[x]==low[x]) ++col,mn[col]=0x7fffffff;
        if(dfn[x]==low[x]){
            do{
                --top,++cnt[col],color[sta[top]]=col;ins[sta[top]]=-1;
                if(mn[col]>a[sta[top]])	 mn[col]=a[sta[top]],mc[col]=0;
                if(mn[col]==a[sta[top]]) ++mc[col];//关键部分
            }while(sta[top]!=x);
            ans1+=mn[col];ans2=ans2*mc[col]%ha;//记录答案
    	}
        
    }
    int main(){
        n=read();for(register int i=1;i<=n;++i) a[i]=read();
        m=read();for(register int i=1,x,y;i<=m;++i){x=read(),y=read(),add(x,y);}
        for(register int i=1;i<=n;++i) if(!dfn[i]) Tarjan(i);//基本操作
        writep(ans1),writeln(ans2);//输出
        return 0;
    }
    
    
  • 相关阅读:
    webgame模块划分
    VC的若干实用小技巧(一)
    反病毒技术:从亡羊补牢到免疫防御
    MySQL 备份和恢复
    企业网络安全整体解决方案
    大型银行核心网络的三层结构设计
    编写"优美"的SHELLCODE
    linux中apache访问控制配置文件。
    网站同步镜像制作!
    Linux远程桌面(vnc)
  • 原文地址:https://www.cnblogs.com/zhenglw/p/10752577.html
Copyright © 2020-2023  润新知