【拓扑、dfs】【cf895】

你是一个由编号从1到n的n只动物组成的动物园的主人。然而,维护动物园是相当昂贵的,所以你决定卖掉它!

众所周知,每种动物都害怕另一种动物。更确切地说,动物i害怕动物ai(ai≠i)。此外,每只动物的成本是已知的,对于动物i,它等于ci。你会按照固定的顺序卖掉你所有的动物。形式上,您需要选择一些排列†p1,p2,…,pn,然后先出售动物p1,然后出售动物p2,依此类推,最后出售动物pn。

当你出售动物ii时,有两种可能的结果:

如果动物 ai 是在动物 i 之前出售的,您将因出售动物i而获得 ci 资金。

如果动物 ai 在动物i之前没有被出售,您出售动物 i 将获得2∙ci的金钱。

你的任务是选择出售动物的顺序,以最大限度地提高总利润。

对于一个动物,如果没有动物害怕它,那么它应该首先被卖出,i--->ai建图,利用拓扑排序依次找到入度为0的点卖出。如果有环的话,找到价值最小的点 id 作为环的终点,a[id]作为环的起点依次卖出(一只动物不会有害怕两种动物的情况,所以不会出现出度为2的情况,也不会出现一个点在两个环上)。

#include<iostream>
#include<cmath>
using namespace std;
const int N=2e5+10;
int a[N];
int c[N];
int d[N];//入度
int q[N];
bool st[N];
int n,id=-1,hh=0,tt=0;
int minv=1e9;
void dfs(int u)
{
	if(st[u]) return ;
	st[u]=1;
	if(c[a[u]]<minv) minv=c[a[u]],id=a[u];
	dfs(a[u]);
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n;//n个动物
		for(int i=1;i<=n;i++) st[i]=0,d[i]=0;
	    for(int i=1;i<=n;i++) cin>>a[i],d[a[i]]++;
	    for(int i=1;i<=n;i++) cin>>c[i];
	    hh=0,tt=0;
	    for(int i=1;i<=n;i++)
	    {
	    	if(d[i]==0)
	    	{
	    		st[i]=1;
	    		q[tt++]=i;
			}
		}
		while(hh<tt)
		{
			int t=q[hh++];
			d[a[t]]--;
			if(d[a[t]]==0)
			{
			 q[tt++]=a[t]; 
			 st[a[t]]=1;     
		    }
		}
		int ans=0;
		for(int i=1;i<=n;i++)
	    {
	    	if(!st[i])
	    	{
	    		minv=c[i];
	    		id=i;
	    		dfs(i);
	    		int x=a[id];
//不会出现出度为2的情况,所以只需要将环上的点依次入队;
	    		do
	    		{
	    			q[tt++]=x;
	    			x=a[x];
				}while(x!=a[id]);
			}
		}
		for(int i=0;i<tt;i++) cout<<q[i]<<' ';
		cout<<endl;
	}
	return 0;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值