-
並查集/DFS-CodeForces 1027D-Mouse Hunt
-
題目鏈接:
D. Mouse Hunt
-
題目基礎:並查集
數據結構-並查集
-
思路:
題目大意:
給定兩個N長度序列,第一個序列表示在每個房間安裝捕鼠器的成本,第二個序列是狀態圖,表示在第 i 個房間的老鼠,下一秒會去到房間 Next_Room[i] (可以選擇停留在該房間),求出一定能捉到老鼠的最小成本
題解:
怎樣放捕鼠器才能讓老鼠一定被捉到?其實就是放在老鼠在房間中活動形成的環路,想要最小成本,在每個環中選出安裝捕鼠器成本最低的房間
那要怎麼檢查老鼠活動是否成環?用到並查集,如果檢查的兩個元素在一個集合中,說明成環(兩種成環狀態,自環-當老鼠停留在原來房間,或者多房間成環)
然後用深搜找出每個環安裝捕鼠器的最小成本
-
代碼:
#include<bits/stdc++.h>
using namespace std;
#define MAX_SIZE 200005
int Node[MAX_SIZE];
int Height[MAX_SIZE];
int Burles[MAX_SIZE];
int Next_Room[MAX_SIZE];
int Judge[MAX_SIZE];
void Init(int n) //初始化結點
{
for(int i=0;i<=n;i++)
{
Node[i]=-1;
Height[i]=0;
Judge[i]=0;
}
}
int Find(int x) //查找集合根
{
if(Node[x]==-1)
return x;
else
return Node[x]=Find(Node[x]); //查找到x的根時,將x直接連到根
}
int Combine(int a,int b) //a b 符合某種關係需合併,如果a b本同屬一個集合,返回0
{
int a_root=Find(a);
int b_root=Find(b);
if(a_root==b_root)
return 0;
if(Height[a_root]<Height[b_root]) //小樹a放在b下
Node[a_root]=b_root;
else
{
Node[b_root]=a_root;
if(Height[a_root]==Height[b_root])
Height[a_root]++;
}
return 1;
}
int DFS(int x,int y)
{
if(x==y)
return Burles[x];
return min(DFS(Next_Room[x],y),Burles[x]);
}
int main()
{
int n;
int Res=0;
cin>>n;
Init(n);
for(int i=1;i<=n;i++)
scanf("%d",&Burles[i]);
for(int i=1;i<=n;i++)
{
scanf("%d",&Next_Room[i]);
if(!Combine(i,Next_Room[i])) //兩個房間已在集合內,說明有成環情況,標記
Judge[i]=1;
}
for(int i=1;i<=n;i++)
{
if(Judge[i])
Res+=DFS(Next_Room[i],i);
}
cout<<Res<<endl;
return 0;
}