Checkposts CodeForces - 427C (SCC裸题) HQG_AC

题意:

给你n个点,m条有向边,现在有你建立一些警察局。

每个点有一个建警察局的代价。

每个警察局能够保卫该点当且仅当警察局能到该点且能返回警察局。

现在问你建若干个警察局的最小代价和方案数是多少。

解析:

强连通裸题。

先把n个点做一个强连通。对于每个强连通分量,其中的点肯定能够互相到达。

强连通分量的建立可以通过 K o s a r a j u T a r j a n 完成

于是我们在每个强连通中记录 M i n [ i ] S u m [ i ] 分别表示强连通分量i中的最小值和最小值的个数

设有k个强连通分量

扫描二维码关注公众号,回复: 2358793 查看本文章

a n s 1 = i = 1 k M i n i
a n s 2 = i = 1 k S u m i

c o u t << a n s 1 <<" "<< a n s 2 << e n d l ; (请勿复制)

最后提醒不要忘记mod!

Code:

K o s a r a j u

#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#define sqr(x) (x)*(x)
#define fz1(i,n) for (i=1;i<=n;i++)
#define fd1(i,n) for (i=n;i>=1;i--)
#define fz0g(i,n) for (i=0;i<=n;i++)
#define fd0g(i,n) for (i=n;i>=0;i--)
#define fz0k(i,n) for (i=0;i<n;i++)
#define fd0k(i,n) for (i=(long long)(n-1);i>=0;i--)
#define fz(i,x,y) for (i=x;i<=y;i++)
#define fd(i,y,x) for (i=y;i>=x;i--)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define rdst(st,len) {char ss[len];scanf("%s",ss);(st)=ss;}
using namespace std;
long long n,m,i,j,col[100005],mi[100005],f[100005],ans,ans2=1,vis[100005],cst[100005],x,y,cnt,mod=1e9+7;
vector<long long> bi[100005],nbi[100005],seq;
void dfs(int x)
{
    if (vis[x]) return;
    vis[x]=1;
    ff(nbi[x],it) dfs(*it);
    seq.push_back(x);
}
void dfs2(int x,int cnt)
{
    if (col[x]) return;
    col[x]=cnt;
    ff(bi[x],it) dfs2(*it,cnt);
}
int main()
{
    scanf("%I64d",&n);
    fz1(i,n) scanf("%I64d",&cst[i]);
    scanf("%I64d",&m);
    fz1(i,m)
    {
        scanf("%I64d%I64d",&x,&y);
        bi[x].push_back(y);
        nbi[y].push_back(x);
    }
    fz1(i,n)
    {
        if (!vis[i])
        {
            dfs(i);
        }
    }
    reverse(seq.begin(),seq.end());
    fz0k(i,n)
    {
        if (!col[seq[i]])
        {
            cnt++;
            mi[cnt]=1ll<<55;
            dfs2(seq[i],cnt);
        }
    }
    fz1(i,n)
    {
        if (cst[i]<mi[col[i]])
        {
            mi[col[i]]=cst[i];
            f[col[i]]=0;
        }
        if (cst[i]==mi[col[i]])
        {
            f[col[i]]++;
        }
    }
    fz1(i,cnt)
    {
        ans+=mi[i];
        (ans2*=f[i])%=mod;
    }
    printf("%I64d %I64d\n",ans,ans2);
    return 0;
}

T a r j a n

#include <bits/stdc++.h>
using namespace std ;
const int inf = 0x3f3f3f3f ;
const int N = 100010 ;
const int mod = 1000000007 ;
vector <int> G[N],link[N] ;
stack <int> S ;
long long dfn[N],low[N],sd[N],cost[N];
bool vis[N] ;
int tot=0,cnt,n,m,x,y ;
void tarjan(int now){
    dfn[now]=low[now]=++tot ;
    vis[now]=true;S.push(now) ;
    for (int i=0;i<G[now].size();i++){
        int to=G[now][i] ;
        if (!dfn[to]){
            tarjan(to) ;
            low[now]=min(low[now],low[to]) ;
        }
        if (dfn[to] && vis[to]) low[now]=min(low[now],low[to]) ;
    }
    if (low[now]==dfn[now]){
        sd[now]=++cnt ;
        vis[now]=false ;
        while(S.top()!=now){
            sd[S.top()]=cnt ;
            vis[S.top()]=false ;
            S.pop() ;
        }
        S.pop() ;
    }
}
int main(){
    scanf("%d",&n) ;
    for (int i=1;i<=n;i++) scanf("%d",&cost[i]) ;
    scanf("%d",&m) ;
    for (int i=1;i<=m;i++){
        scanf("%d%d",&x,&y) ;
        G[x].push_back(y) ;
    } 
    memset(dfn,0,sizeof(dfn)) ;
    memset(low,0,sizeof(low)) ;
    memset(vis,false,sizeof(vis)) ;
    for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i) ;
    for (int i=1;i<=n;i++) link[sd[i]].push_back(i) ;
    long long ans=0,anssum=1 ;
    for (int i=1;i<=cnt;i++){
        int minn=inf,minnsum=0 ;
        for (int j=0;j<link[i].size();j++){
            int poi=link[i][j] ;
            if (minn>cost[poi]){
                minnsum=1  ;
                minn=cost[poi] ;
            }
            else if (minn==cost[poi]) minnsum++ ;
        }
        ans+=minn ;
        anssum=(anssum*minnsum)%mod ;
    }
    printf("%lld %lld",ans,anssum) ;
}

猜你喜欢

转载自blog.csdn.net/hqg_ac/article/details/81143563