luogu P2194 HXY烧情侣

残忍的题面

我们来看这一道题,其实冗长的题目告诉我们一个核心——用tarjan

tarjan是用来干什么呢?是用来求强连通分量(代码中指sc)

求出来又有什么用呢?每当我们求出一个强连通分量时,就去计算当前强连通分量中各点最小值是多少以及其个数

然后分别开两个计数器,假设ans1是用来存个数相乘,ans2是用来累加最小值的。

临门一脚,千万别忘了取% 另外注意如果小伙伴这样和我一样写tarjan的话

for(int i=head[x];i!=-1;i=e[i].next)

一定记住,在main函数里要

memset(head,-1,sizeof(head));

(看本蒟蒻的代码,大神勿喷)

#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
#define ll long long
#define inf 1e9
const int N = 310000;
const int M = 210000;
int head[M],v[M],dfn[M],low[M],q[M];
int be[M],sum[M],hh[M],num[M];
int ss,n,m,now,cnt,tot,sc;
ll ans1=1,ans2;
bool f[N];
struct Edge{
    int to,next;
}e[N];
void add(int x,int y)
{
    e[++ss].to=y;
    e[ss].next=head[x];
    head[x]=ss;
}
void dfs(int x)//这里的dfs和下面tarjan分着写的,不管怎样都是tarjan模板
{
    low[x]=dfn[x]=++cnt;
    q[++tot]=x;
    f[x]=1;
    for(int i=head[x];i!=-1;i=e[i].next)
    {
        if(!dfn[e[i].to])
        {
            dfs(e[i].to);
            low[x]=min(low[x],low[e[i].to]);
        }
        else
        if(f[e[i].to])
        low[x]=min(low[x],dfn[e[i].to]);
    }
    if(low[x]==dfn[x])
    {
        sc++;
        be[x]=sc;
        hh[sc]=inf;
        do
        {
            now=q[tot--];
            f[now]=0;
            be[now]=sc;
            if(v[now]<hh[sc])
            {
                hh[sc]=v[now];
                num[sc]=0;
            }
            if(v[now]==hh[sc]) num[sc]++;
        }
        while(now!=x);
    }
}
void tarjan()
{
    for(int i=1;i<=n;i++)
        if(!dfn[i]) dfs(i);
}
int main()
{
    memset(head,-1,sizeof(head));
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>v[i];
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        add(x,y);
    }
    tarjan();
    for(int i=1;i<=sc;i++)//最后的处理,ans1别忘初值为1
    {
        ans1*=num[i];
        ans2+=hh[i];
        ans1%=mod;
    }
    cout<<ans2<<" "<<ans1;
    return 0;
}

 

posted @ 2018-12-24 14:53  xmex  阅读(188)  评论(3编辑  收藏  举报