Codeforces Round #244 (Div. 2) C. Checkposts

裸的tarjan

依题意有向图上i和j之间能互相到达,i和j肯定在同一个scc内

最小的代价就是Σ每个scc内最小的cost

方案就是每个scc内最小值的数的乘积

#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
const int maxn=int(1e5)+7;
int n,m,s,num=0,step=0,Scc=0,dp[maxn],rd[maxn],weight[maxn],scc[maxn],dfn[maxn],flag[maxn],low[maxn],stap[maxn];
long long minscc[maxn],p[maxn],w[maxn];
struct lys{
    int from,to,next;
}e[maxn*7];
int cnt=0,head[maxn*7];
void add(int from,int to){
    cnt++;e[cnt].from=from;e[cnt].to=to;e[cnt].next=head[from];head[from]=cnt;
}
struct lys2{
    int from,to,next;
}e2[maxn*7];
int cnt2=0,head2[maxn*7];
void add2(int from,int to){
    cnt2++;e2[cnt2].from=from;e2[cnt2].to=to;e2[cnt2].next=head2[from];head2[from]=cnt2;
}
void init(){
    memset(flag,0,sizeof(flag));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(stap,0,sizeof(stap));
    for(int i=1;i<=n;i++) scc[i]=i,minscc[i]=mod;
}
void tarjan(int u){   flag[u]=1;
    dfn[u]=low[u]=++step;
    stap[++num]=u;//压栈
    for (int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if (dfn[v]==0)
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if (flag[v]==1)
            low[u]=min(low[u],dfn[v]);
    }
    int v;
    if (dfn[u]==low[u])
    { 
        Scc++;//联通块标号
        int cnt=0;
        vector<int>tmp;
        do{
            v=stap[num--];
            flag[v]=0;
            scc[v]=Scc;//v属于第Scc个联通块
            minscc[Scc]=min(minscc[Scc],w[v]);
            tmp.push_back(w[v]);
            if(u==v) continue;
        }
        while (v!=u);
        for(auto v:tmp){
            if(v==minscc[Scc]) p[Scc]++;
        }
    }
}
queue<int>q;
void out( )
{    
   long long ans=0;
   for(int i=1;i<=Scc;i++) ans=(ans+minscc[i]);
   long long way=1;
   for(int i=1;i<=Scc;i++) way=way*p[i]%mod;
   cout<<ans<<" "<<way%mod;
}
int main( )
{
    //freopen("lys.in","r",stdin);
    cin>>n;
    init();
    for(int i=1;i<=n;i++) cin>>w[i];
    cin>>m;
    for(int i=1;i<=m;i++){
        int a,b;cin>>a>>b;
        add(a,b);
    }

    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i);
    
     out();
}

 

posted @ 2023-02-05 21:45  liyishui  阅读(14)  评论(0编辑  收藏  举报