ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

水晶铭刻之旅【牛客tracker 每日一题】

水晶铭刻之旅【牛客tracker  每日一题】

水晶铭刻之旅

时间限制:1 秒
空间限制:256M

网页链接

牛客tracker

牛客tracker & 每日一题,完成每日打卡,即可获得牛币。获得相应数量的牛币,能在【牛币兑换中心】,换取相应奖品!助力每日有题做,丰盈牛币日益多!


题目描述

在远古魔法世界中,有n nn块蕴含强大力量的魔法水晶,第i ii块水晶的激活需要消耗魔力w i w_iwi​。这些水晶之间由m mm条单向传送门相连,第j jj条传送门可将咒术师从水晶x j x_jxj​传送到水晶y j y_jyj​。

咒术师掌握了"回路铭刻术":

请帮助咒术师:

【名词解释】


输入描述


输出描述

输出一行,包含两个整数:


示例 1

输入:

3 1 2 3 3 1 2 2 3 3 2

输出:

3 1

说明:示例中,水晶{ 2 , 3 } \{2,3\}{2,3}构成回路,可选起点魔力为min ⁡ ( 2 , 3 ) = 2 \min(2,3) = 2min(2,3)=2;水晶1 11独立,付费1 11。总魔力1 + 2 = 3 1 + 2 = 31+2=3,方案数1 × 1 = 1 1 \times 1 = 11×1=1。


示例 2

输入:

3 10 20 10 4 1 2 1 3 3 1 2 1

输出:

10 2

说明:示例中,所有水晶互联可形成回路,回路中最小激活魔力为10 1010(可选水晶1 11或3 33),故方案数为2 22。


数据范围

解题思路

本题是强连通分量缩点 + 贪心计数的经典问题。给定一张有向图,每个节点有一个激活魔力值,一次“回路铭刻”可以从某个节点出发,沿着有向边行走并最终回到起点,路径上经过的所有节点均可被一次性铭刻,总消耗仅为起点节点的激活魔力。要求用若干次回路铭刻覆盖所有节点,最小化总消耗,并统计达到最小消耗的方案数。

1. 问题等价转化
2. 算法实现
  1. 建图:读入节点数n nn、每个节点的魔力值w i w_iwi​、边数m mm以及m mm条有向边,使用链式前向星存储。
  2. Tarjan 求强连通分量:
    • 使用dfn和low数组进行深度优先搜索,维护一个栈stk记录当前搜索路径上的节点。
    • 当dfn[u] == low[u]时,说明找到了一个强连通分量,从栈中弹出节点直到u uu,为这些节点分配同一个 SCC 编号。
    • 在弹出节点的过程中,统计该 SCC 内的最小魔力值minCost以及达到该最小值的节点个数minCnt。
  3. 统计答案:
    • 遍历所有 SCC,将每个 SCC 的minCost累加到总消耗sum中。
    • 将每个 SCC 的minCnt累乘到方案数ways中(对10 9 + 7 10^9+7109+7取模)。
  4. 输出:输出总消耗sum和方案数ways。
3. 复杂度分析

总结

利用强连通分量将图缩点,每个 SCC 内部可以通过一次回路铭刻完全覆盖,且选择其中魔力最小的节点作为起点即可使该分量消耗最小。各 SCC 相互独立,总消耗为各分量最小魔力之和,方案数为各分量最小魔力节点个数的乘积。Tarjan 算法在线性时间内求出所有 SCC 并统计信息,整体思路清晰且高效。

代码内容

#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'typedeflonglongll;typedefunsignedlonglongull;typedefvector<vector<ll>>vvt;typedefpair<ll,ll>pll;constll N=200000+10;constll M=1000000+10;constll mod=1000000007;constll INF=1e9;ll head[N],to[M],nxt[M],idx;ll cost[N],dfn[N],low[N],stk[N],sccId[N];ll minCost[N],minCnt[N];boolinStk[N];ll n,m,timerCnt,top,sccCnt;voidaddEdge(ll u,ll v){to[++idx]=v;nxt[idx]=head[u];head[u]=idx;}voidtarjan(ll u){dfn[u]=low[u]=++timerCnt;stk[++top]=u;inStk[u]=true;for(ll i=head[u];i!=0;i=nxt[i]){ll v=to[i];if(dfn[v]==0){tarjan(v);low[u]=min(low[u],low[v]);}elseif(inStk[v]){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){sccCnt++;minCost[sccCnt]=INF;minCnt[sccCnt]=0;while(true){ll x=stk[top--];inStk[x]=false;sccId[x]=sccCnt;if(cost[x]<minCost[sccCnt]){minCost[sccCnt]=cost[x];minCnt[sccCnt]=1;}elseif(cost[x]==minCost[sccCnt]){minCnt[sccCnt]++;}if(x==u)break;}}}intmain(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);cin>>n;for(ll i=1;i<=n;i++){cin>>cost[i];}cin>>m;for(ll i=1;i<=m;i++){ll u,v;cin>>u>>v;addEdge(u,v);}for(ll i=1;i<=n;i++){if(dfn[i]==0){tarjan(i);}}ll sum=0;ll ways=1;for(ll i=1;i<=sccCnt;i++){sum+=minCost[i];ways=ways*minCnt[i]%mod;}cout<<sum<<" "<<ways;return0;}
返回列表