Codeforces B. Mouse Hunt(强连通分解缩点)

题目描述:

Mouse Hunt

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Medicine faculty of Berland State University has just finished their admission campaign. As usual, about 80%of applicants are girls and majority of them are going to live in the university dormitory for the next

4(hopefully) years.

The dormitory consists of n rooms and a single mouse! Girls decided to set mouse traps in some rooms to get rid of the horrible monster. Setting a trap in room number costs \(c_i\) burles. Rooms are numbered from 1 to n

Mouse doesn‘t sit in place all the time, it constantly runs. If it is in room i in second then it will run to room \(a_i\) without visiting any other rooms inbetween (i=\(a_i\)means that mouse won‘t leave room i) It ‘s second 0 in the start.If the mouse is in some room with a mouse trap in it, then the mouse get caught into this trap.

That would have been so easy if the girls actually knew where the mouse at. Unfortunately, that‘s not the case, mouse can be in any room from 1 to at second 0

What it the minimal total amount of burles girls can spend to set the traps in order to guarantee that the mouse will eventually be caught no matter the room it started from?

Input

The first line contains as single integers n(\(1\leq n\leq 2*10^5\)) — the number of rooms in the dormitory.

The second line contains nintegers \(c_1,c_2,...,c_n\) (1≤\(c_i\)≤\(10^4\))is the cost of setting the trap in room number i

The third line contains nintegers \(a_1,a_2,...,a_n\)(1≤\(a_i\)n) is the room the mouse will run to the next second after being in room i

Output

Print a single integer — the minimal total amount of burles girls can spend to set the traps in order to guarantee that the mouse will eventually be caught no matter the room it started from.

Examples

Input

Copy

51 2 3 2 101 3 4 3 3

Output

Copy

3

Input

Copy

41 10 2 102 4 2 2

Output

Copy

10

Input

Copy

71 1 1 1 1 1 12 2 2 3 6 7 6

Output

Copy

2

Note

In the first example it is enough to set mouse trap in rooms 1 and 4. If mouse starts in room 1.then it gets caught immideately. If mouse starts in any other room then it eventually comes to room 4.

In the second example it is enough to set mouse trap in room 2. If mouse starts in room then it gets caught immideately. If mouse starts in any other room then it runs to room 2 in second 1.

Here are the paths of the mouse from different starts from the third example:

1→2→2→…;

2→2→…;

3→2→2→…;

4→3→2→2→…;

5→6→7→6→…;

6→7→6→…;

7→6→7→…;

So it‘s enough to set traps in rooms 2 and 6.

思路:

题目是说各一个数组a,其中i指向ai,也就是给了一个图,这个图是老鼠行程,根据这个图我们可以看到老鼠最终会在某个点停下,要么会一直的兜圈子。要求不管老鼠一开始在哪个房间,以某种代价最小的方式放置捕鼠夹,使得最后定能捕住老鼠。求这个最小代价。

我们发现只要在老鼠停下来的地方或者环上代价最小的一个地方放置捕鼠夹就能捕住老鼠。其实这道题就可以看成是图的强连通分解,通过tarjan算法求这个图有多少个强连通块,最后求出的强连通块再进行缩点,把一个强连通块看成一个点,并存储这个强连通块上的最小代价。最后要求的点是出度为0的点,为什么?因为出度为零的点就是最后老鼠停下来的点和环(已经缩点)。

需要注意的是缩点的一些细节,记录好强连通块的数目,每个强连通块建立对应的最小代价数组,遍历一遍点求出每个强连通块对应的最小代价,和每个强连通块的出度(只要有边相连的两个点不在一个强连通块上出度就减小一。最后遍历每个强连通块,求出出度为零的强连通块的最小代价和。

代码:

#include <iostream>
#include <cstdio>
#include <stack>
#define max_n 200005
#define INF 0x3f3f3f3f
using namespace std;
//题目数据
int a[max_n];
int c[max_n];
int n;
//链式前向星
int cnt = 0;
int head[max_n];
struct
{
    int v;
    int next;
}e[max_n<<1];
void add(int u,int v)
{
    ++cnt;
    e[cnt].v = v;
    e[cnt].next = head[u];
    head[u] = cnt;
}
//读入优化
template<typename T>
inline void read(T& x)
{
    x = 0;int f = 0;char ch = getchar();
    while(ch<'0'||ch>'9') {f |= (ch=='-');ch = getchar();}
    while(ch>='0'&&ch<='9') {x = x*10+ch-'0';ch = getchar();}
    x = f?-x:x;
}
//tarjan算法
int Bcnt = 0;
int idx = 0;
int dfn[max_n];
int low[max_n];
int instack[max_n];
int Belong[max_n];
stack<int> s;
int Deg[max_n];
int cost[max_n];
void tarjan(int u)
{
    dfn[u] = low[u] = ++idx;
    s.push(u);
    instack[u] = 1;
    int v;
    for(int i = head[u];i;i=e[i].next)
    {
        v = e[i].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u],low[v]);
        }
        else if(instack[v])
        {
            low[u] = min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        Bcnt++;
        do
        {
            v = s.top();
            s.pop();
            instack[v] = 0;
            Belong[v] = Bcnt;
        }while(u!=v);
    }
}
void solve()
{
    for(int i = 1;i<=n;i++)
    {
        cout << "d " << dfn[i] << " l " << low[i] << endl;
    }
    cout << "共有 " << Bcnt << " 个连通分量" << endl;
    for(int i = 1;i<=Bcnt;i++)
    {
        cout << "第 " << i << "个 " << endl;
        for(int j = 1;j<=n;j++)
        {
            if(Belong[j]==i)
            {
                cout << j << " ";
            }
        }
        cout << endl;
    }
}
int main()
{
    read(n);
    for(int i = 1;i<=n;i++)
    {
        read(c[i]);
    }
    for(int i = 1;i<=n;i++)
    {
        read(a[i]);
        add(i,a[i]);//建边
    }
    for(int i = 1;i<=n;i++)
    {
        if(!dfn[i])
        {
            tarjan(i);
        }
    }
    //solve();
    //缩点
    for(int i = 1;i<=Bcnt;i++)
    {
        cost[i] = INF;
    }
    for(int i = 1;i<=n;i++)
    {
        cost[Belong[i]] = min(cost[Belong[i]],c[i]);//求出每个强连通分量的最小cost
    }
    for(int i = 1;i<=n;i++)
    {
        if(Belong[i]!=Belong[a[i]])
        {
            Deg[Belong[i]]++;//如果连个相连的点不在一个强连通分量里面,那么他所属的强连通分量的出度加一
        }
    }
    /*for(int i =1;i<=n;i++)
    {
        cout << "Deg " << i << " : " << Deg[i] << endl;
    }*/
    int ans = 0;
    for(int i = 1;i<=Bcnt;i++) //遍历所有的强连通分量
    {
        //cout << "deg " << i << ":" << Deg[i] << endl;
        if(Deg[i]==0)
        {
            ans += cost[i];//如果该连通分量的出度为一,则比在这个连通分量上放一个捕鼠夹
        }
    }
    cout << ans << endl;
    return 0;
}

参考文章:

悠悠呦~,Codeforces 1027D Mouse Hunt (强连通缩点 || DFS+并查集),https://www.cnblogs.com/00isok/p/10394721.html

原文地址:https://www.cnblogs.com/zhanhonhao/p/11296017.html

时间: 2024-10-04 23:41:48

Codeforces B. Mouse Hunt(强连通分解缩点)的相关文章

UVALIVE 4287 Proving Equivalences (强连通分量+缩点)

题意:给定一个图,问至少加入多少条边能够使这个图强连通. 思路:首先求出这个图的强连通分量.然后把每个强连通分量缩成一个点.那么这个图变成了一个DAG,求出全部点的入度和出度,由于强连通图中每个节点的入度和出度至少为1.那么我们求出入度为零的节点数量和出度为零的节点数量.答案取最大值,由于在一个DAG中加入这么多边一定能够使这个图强连通.注意当这个图本身强连通时要特判一下,答案为零. #include<cstdio> #include<cstring> #include<cm

ZOJ3795 Grouping(强连通分量+缩点+记忆化搜索)

题目给一张有向图,要把点分组,问最少要几个组使得同组内的任意两点不连通. 首先考虑找出强连通分量缩点后形成DAG,强连通分量内的点肯定各自一组,两个强连通分量的拓扑序能确定的也得各自一组. 能在同一组的就是两个强连通分量在不同的从入度0到出度0的强连通分量的路径上. 那么算法很直观就能想到了,用记忆化搜索,d[u]表示从强连通分量u出发到出度为0的强连通分量最少要几个组(最多有几个点). 1 #include<cstdio> 2 #include<cstring> 3 #inclu

【连通图|强连通分量+缩点】POJ-1236 Network of Schools

Network of Schools Time Limit: 1000MS Memory Limit: 10000K Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes softwa

UVA 11324 The Largest Clique (强连通分量缩点,图DP)

题目: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意: 给你一个有向图,求一个点集合的最大大小,使得此点集合中对于任意点对(u,v),有从u到v或者从v到u的边 方法: 先找强连通分量缩点,每个强连通分量显然满足条件,然后在缩点后的图中找到一条权值最大的路径,权值为此路径的点权之和,点权为这个

【差分约束系统】【强连通分量缩点】【拓扑排序】【DAG最短路】CDOJ1638 红藕香残玉簟秋,轻解罗裳,独上兰舟。

题意: 给定n个点(点权未知)和m条信息:u的权值>=v的权值+w 求点权的极小解和极大解(无解则输出-1) 极小解即每个点的点权可能的最小值 极大解即每个点的点权可能的最大值 题解: 差分约束系统 对于val[u]>=val[v]+w 要得到极小解,v是没有受限制的,其最小值为0 而u受到v的限制,显然,val[u]的最小值就是val[v]+w 在多条件限制下,我们用v连向u边权为w的边表示每个限制条件val[u]>=val[v]+w 那么如果得到的是拓扑图,则按拓扑序求到每个点的最长

【强连通分量缩点】【拓扑排序】【dp预处理】CDOJ1640 花自飘零水自流,一种相思,两处闲愁。

题意: 在n个点m条边的有向图上,从1出发的回路最多经过多少个不同的点 可以在一条边上逆行一次 题解: 在同一个强连通分量中,显然可以经过当中的每一个点 因此先将强连通分量缩点,点权为强连通分量的点数 如果不逆行,那么答案就是1所在的强连通分量的点数 如果逆行了,那么逆行的边必然在缩点后的拓扑图上 假设逆行的边为u->v,那么该回路可分为1到v和u到1两部分 经过的最多点数即1到v与u到1路径上的最大点权和减去1的点权 (这里的点指的都是缩点后的点) 例子中在边4->3上逆行就能从1出发经过所

POJ1236Network of Schools(强连通分量 + 缩点)

题目链接Network of Schools 参考斌神博客 强连通分量缩点求入度为0的个数和出度为0的分量个数 题目大意:N(2<N<100)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件.2,至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件.   也就是: ?        给定一个有向图,求:   1) 至少要选几个顶

POJ2553 The Bottom of a Graph(强连通分量+缩点)

题目是问,一个有向图有多少个点v满足∀w∈V:(v→w)⇒(w→v). 把图的强连通分量缩点,那么答案显然就是所有出度为0的点. 用Tarjan找强连通分量: 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define MAXN 5555 6 #define MAXM 5555*5555 7 struct Edge{ 8 int u,v,nex

POJ 3114 - Countries in War(强连通分量+缩点+拓扑排序+DAG最短路)

Countries in War Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Appoint description: Description In the year 2050, after different attempts of the UN to maintain peace in the world, the third world war broke out. The impor