HXY burning couple

Los goo

Meaning of the questions: There are n cinemas, n couple were at each seat movie theater, the cinema and then have gasoline, but to use it at a fee .m unidirectional channel connecting two adjacent movie theater where the couple then. HXY have a stunt, a point if she could start to burn, and finally return to this point, then burn a couple this loop of the cost of gasoline just to the point. and each couple just burn it again, cinema can be repeated to go. then she wanted to spend as little as possible the cost of burn all lovers. ask how much the minimum required, and when the minimum number of program cost is how much? Since the number of programs may be too large, so the number of output scheme please \ (1e9 + 7 \) results modulo.

(Note: This can start every HXY back from any point in a circuit path that is completed, the next starting position it can optionally say there is not the burning of all couples, even if FIG does not communicate, HXY choose. vertices burn a couple of action and the path taken away can be repeated.)

Analysis: According to the meaning of the questions, a point strongly connected components which can be burned at the same time, the cost to a minimum for all points inside so we ran a directed graph. \ (Tarjan \) reduction points, while recording each strongly connected component inside minimum cost and minimum cost of a few points (to facilitate output scheme, the cost of the program is the product of the minimum number for each strongly connected components).

Then directly enumerate every strongly connected component, the answer can be calculated separately.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int mod=1e9+7;
const int N=100005;
const int M=300005;
ll ans1,ans2=1;
int n,m,w[N],a[M],b[M];
int tim,top,num,dfn[N],low[N],st[N],color[N],val[N][2];
//val[i][0]表示第i个强连通分量的费用最小值
//val[i][1]表示第i个强连通分量的费用最小值的个数
int tot,head[N],nxt[M],to[M];
inline void add(int a,int b){
    nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
}
inline void tarjan(int u){
    dfn[u]=low[u]=++tim;st[++top]=u;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!color[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        color[u]=++num;
        val[num][0]=w[u];val[num][1]=1;
        while(st[top]!=u){
            color[st[top]]=num;
            if(w[st[top]]<val[num][0]){
                val[num][0]=w[st[top]];
                val[num][1]=1;
            }
            else if(w[st[top]]==val[num][0])++val[num][1];
            --top;
        }
        --top;
    }
}
int main(){
    n=read();for(int i=1;i<=n;++i)w[i]=read();
    m=read();
    for(int i=1;i<=m;++i){
        a[i]=read();b[i]=read();
        add(a[i],b[i]);
    }
    for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);
    for(int i=1;i<=num;++i){
        ans1+=val[i][0];//累加每个强连通分量的费用最小值
        ans2=(ans2*val[i][1])%mod;//乘法原理计算方案
    }
    printf("%lld %lld\n",ans1,ans2);
    return 0;
}

Guess you like

Origin www.cnblogs.com/PPXppx/p/11579263.html