zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    【题解】魔术棋子
    NHOI2019小结
    【题解】滑雪
    【题解】最大平台
    【题解】洪水
    【题解】N皇后问题
    【题解】四色定理
    使用Docker快速搭建Jenkins
    使用Docker快速搭建Gitlab
    测试用Docker Swarm环境搭建
  • 原文地址:https://www.cnblogs.com/czy-power/p/10447715.html
Copyright © 2011-2022 走看看