protagonist

HXY烧情侣

题目描述

众所周知,HXY已经加入了FFF团。现在她要开始喜(sang)闻(xin)乐(bing)见(kuang)地烧情侣了。这里有n座电影院,n对情侣分别在每座电影院里,然后电影院里都有汽油,但是要使用它需要一定的费用。m条单向通道连接相邻的两对情侣所在电影院。然后HXY有个绝技,如果她能从一个点开始烧,最后回到这个点,那么烧这条回路上的情侣的费用只需要该点的汽油费即可。并且每对情侣只需烧一遍,电影院可以重复去。然后她想花尽可能少的费用烧掉所有的情侣。问最少需要多少费用,并且当费用最少时的方案数是多少?由于方案数可能过大,所以请输出方案数对1e9+7取模的结果。

(注:这里HXY每次可以从任何一个点开始走回路。就是说一个回路走完了,下一个开始位置可以任选。所以说不存在烧不了所有情侣的情况,即使图不连通,HXY自行选择顶点进行烧情侣行动。且走过的道路可以重复走。)

输入输出格式

输入格式:

 

第一行,一个整数n。

第二行,n个整数,表示n个情侣所在点的汽油费。

第三行,一个整数m。

接下来m行,每行两个整数xi,yi,表示从点xi可以走到yi。

 

输出格式:

 

一行,两个整数,第一个数是最少费用,第二个数是最少费用时的方案数对1e9+7取模

 

输入输出样例

输入样例#1: 复制
3
1 2 3
3
1 2
2 3
3 2
输出样例#1: 复制
3 1
输入样例#2: 复制
3
10 20 10
4
1 2
1 3
3 1
2 1
输出样例#2: 复制
10 2

说明

数据范围:

对于30%的数据,1<=n,m<=20;

对于10%的数据,保证不存在回路。

对于100%的数据,1<=n<=100000,1<=m<=300000。所有输入数据保证不超过10^9。

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
#define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
#define PER(i, a, b) for(int i = (a); i >= (b); -- i)
using namespace std;
const int maxn=5e5+5;
const int mod=1e9+7;
template <class T>
inline void rd(T &ret){
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9'){
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}
struct node{int to,nx;}p[maxn];
int vis[maxn],val[maxn],head[maxn],n,m,tot,cnt,ans,fn,dfn[maxn],low[maxn],my;
void addedge(int u,int v){
     p[++tot].to=v,p[tot].nx=head[u],head[u]=tot;
}
vector<int>v[maxn];
stack<int>sk;
void tarjan(int s){
      dfn[s]=low[s]=++cnt;
      vis[s]=1;
      sk.push(s);
      for(int i=head[s];i;i=p[i].nx){
            int to=p[i].to;
            if(!dfn[to]){
                tarjan(to);
                low[s]=min(low[s],low[to]);
            }
            else if(vis[to]) low[s]=min(low[s],dfn[to]);
      }
      if(dfn[s]==low[s]){
           int cur;
           ++my;
           do{
               cur=sk.top();
               sk.pop();
               vis[cur]=0;
               v[my].push_back(cur);
           }while(cur!=s);
      }
}
int main()
{
    rd(n);
    fn=1;
    REP(i,1,n)rd(val[i]);
    rd(m);
    REP(i,1,m){
        int u,v;
        rd(u),rd(v);
        addedge(u,v);
    }
    REP(i,1,n){
       if(!dfn[i])tarjan(i);
    }
    REP(i,1,my){
        int cur=v[i].size(),tmp=0,minn=mod;
        for(int j=0;j<cur;j++){
            if(minn>val[v[i][j]]){
                minn=val[v[i][j]];
                tmp=1;
            }
            else if(minn==val[v[i][j]]) tmp++;
        }
        ans+=minn;
        fn=(fn%mod*tmp%mod)%mod;
    }
    cout<<ans<<' '<<fn<<endl;
    return 0;
}

 

posted @ 2019-02-27 23:07  czy-power  阅读(156)  评论(0编辑  收藏  举报