首页 > 其他分享 >P1262 间谍网络 题解

P1262 间谍网络 题解

时间:2024-07-12 13:31:19浏览次数:16  
标签:连通 cost min int 题解 3200 间谍 low P1262

题目描述

给你一个有向图,可以付出代价获取一些指定的点。
在获取之后要求能以获取的点为出发点,将整个图都访问到,求最小的代价

思路

既然需要令总的代价最少,那么如果通过买一个点就可以访问到的所有点,自然会比买两个点的方案更优
于是自然的就可以联想到可以将图划分成很多个强连通图,只要在这个图中有一个点访问到了,整个强连通图就被访问到了。

既然要求强连通图,那么就自然的需要用到tarjan算法了。
再求出图内的所用强连通图之后对它们进行缩点,这样就只要能访问这个点就可以了。

但是因为在缩点之后就不能简单的遍历这个强连通图,所以我们就需要将这个强连通图中代价最小的一个点记录下来。
这就需要使用一个辅助数组 min_cost 来记录。
具体的实现也很简单,只需要在将栈内的元素弹出时进行比较就可以了。

AC Code

#include<bits/stdc++.h>
using namespace std;
int n,r,p,dfn[3200],low[3200],group[320![](file://C:/Users/Administrator/Documents/Gridea/post-images/1704207640718.jpg)0],in[3200],cost[3200],cnt,num,min_cost[3200],ans;
bool vis[3200];
vector<int> v[3200];
stack<int> s; 
void tarjan(int x){ //tarjan的板子+缩点
	dfn[x]=low[x]=++num; 
	vis[x]=1;
	s.push(x);
	for(int i:v[x]){ //依次便利v[x]中的元素赋值给i
		if(!dfn[i]){
			tarjan(i);
			low[x]=min(low[x],low[i]);
		}else if(vis[i])
			low[x]=min(low[x],dfn[i]);
	}if(dfn[x]==low[x]){ //如果有环
		group[x]=++cnt; 
		min_cost[cnt]=cost[x]; 
		vis[x]=0;
		while(s.top()!=x){ //栈内有强连通图内的元素
			group[s.top()]=cnt; 
			min_cost[cnt]=min(min_cost[cnt],cost[s.top()]);
			vis[s.top()]=0;
			s.pop();
		}s.pop(); 
	}return ;
}int find(int x){ //寻找这个强连通图内最小的点
	for(int i=1;i<=n;i++)
		if(group[i]==x) 
			return i; 
	return n;
}int main(){
	memset(cost,0x3f,sizeof(cost));  //区分是否可以买
	cin>>n>>p;
	for(int i=1,a,b;i<=p;i++){
		cin>>a>>b;
		cost[a]=b;
	}cin>>r;
	for(int i=1,a,b;i<=r;i++){
		cin>>a>>b;
		v[a].push_back(b); //标记可以通过a直接访问到b
	}for(int i=1;i<=n;i++){
		if(!dfn[i]&&cost[i]!=0x3f3f3f3f3f) //要判断是否可以买
			tarjan(i);
	}for(int i=1;i<=n;i++){
		for(int j:v[i]){ //依次便利v[i]中的元素赋值给i
			if(group[j]!=group[i])
				in[group[j]]++;
		}
	}for(int i=1;i<=cnt;i++){
		if(in[i]==0){ //因为入度为0,所以访问到这个具相当于将这一坨都购买了,比买有入度的点划算
			ans+=min_cost[i];
			if(min_cost[i]==0x3f3f3f3f){ //如果这个区间都不能买就不行
				cout<<"NO"<<endl;
				cout<<find(i)<<endl;
				return 0;
			}
		}
	}cout<<"YES"<<endl;
	cout<<ans<<endl;
	return 0;
}

标签:连通,cost,min,int,题解,3200,间谍,low,P1262
From: https://www.cnblogs.com/liudagou/p/18298195

相关文章

  • [ABC328D] Take ABC 题解
    题目翻译题目描述给你一个字符串\(S\)包含A、B和C三个不用的字符。只要字符串\(S\)中包含连续的ABC就将ABC删除掉再字符串\(S\)不能操作之后输出这个字符串限制\(S\)的长度小于\(2\times10^5\)思路1总结一下这道题目的操作,可以发现就是将字符串删除一......
  • [HNOI2005] 狡猾的商人's 题解
    题目描述给你一个\(n\)元一次方程,判断是否有解,方程给出的格式为\(a-b=c\)思路这道题看上去是一道题目看上去就是判断给出条件是否有矛盾,所以就自然而然的可以使用带权并查集但是因为我太懒了并且这道题目要求使用差分约束系统进行求解,于是就需要将题目转化一下因为差分约束......
  • Ubuntu系统下相关问题解决方案(亲测)
    系统:ubuntu20.04记录使用ubuntu系统过程中遇到的一些问题以及亲测有效的解决方案后续遇到其他问题,会将相关内容持续更新对应原文:Ubuntu系统下相关问题解决方案(亲测)-知乎(zhihu.com)目录一、速度问题1.1gitcloneGithub上的项目时速度慢1.2ubuntu下设置pip加速1.......
  • [CF1656G] Cycle Palindrome 的题解
    题目大意给定一个长度为\(n\)的数列\(a\),要求求出一个排列\(p\)满足\(a_{p_1},a_{p_2},\cdots,a_{p_n}\)是一个回文字符串而且把\(i\)向\(p_i\)连边得到的图中只有一个环。数据范围满足,\(1\le\sumn\le2\times10^5\)。思路先不考虑\(p\)是否构成满足要求的环......
  • [CF1646F] Playing Around the Table 的题解
    题目大意有\(n\)种牌,一种\(n\)张,一共\(n\)个玩家,一人\(n\)个。每个人一次将一张牌对给下家,求构造方案使可以在\(n\cdot(n-1)\)次操作之内使第\(i\)个人拥有\(n\)张\(i\)。数据范围满足,\(1\len\le100\)。思路因为直接构造出题目要求的情况会出现如果一个人提......
  • 2022 RoboCom CAIP(本科组)国赛个人题解
    RC-u1智能红绿灯为了最大化通行效率同时照顾老年人穿行马路,在某养老社区前,某科技公司设置了一个智能红绿灯。这个红绿灯是这样设计的:路的两旁设置了一个按钮,老年人希望通行马路时会按下按钮;在没有人按按钮的时候,红绿灯一直为绿灯;当红绿灯为绿灯时,有人按下按钮,第一次按下......
  • CF1992场题解
    OnlyPluses算法:数学。题意简述:有三个数,每次选择一个数\(x\),使得\(x\)增加一,至多操作\(5\)次,最后求出这三个数的乘积最大值。简单题,一眼秒了。考虑把这\(3\)个数从小到大排序,显然加最小的数比加其他的数更优。简单证一下:设排序后的三个数为\(a,b,c\),有\(b\timesc\ge......
  • upload-labs靶场全题解
    ​​靶场搭建对php和apache版本有严格要求,建议使用phpstudy2018并且使用设置php版本为5.2.17,这个靶场比较老了,如果要复现的话,必要严格按照要求来使用,博主使用最新版的phpstudy在某些靶场上未能成功复现,所以浪费了很多时间。。。。。Upload-Labs环境要求操作系统:wind......
  • 2024SCAU暑假集训_1题解(部分,待补充)
    最近我们开始了暑假集训现在我来补一下第一场集训的题解题目题号来源是否写了题解A黑暗爆炸4771否但是放了大佬的链接指路B黑暗爆炸3399已写C洛谷P3231D洛谷P2120ECodeForces197AF洛谷P1732GBZOJ5296H黑暗爆炸1406......
  • 多线程中自定义线程池与shiro导致的权限错乱问题解决
    importorg.apache.shiro.SecurityUtils;importorg.apache.shiro.subject.Subject;importorg.apache.shiro.util.ThreadContext;importjava.util.concurrent.*;publicclassShiroAwareThreadPoolExecutorextendsThreadPoolExecutor{publicShiroAwareThread......