由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。
我们的反间谍机关提供了一份资料,包括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。
请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。
前置知识:
分析
会了强联通分量以后呢,我们可以开始写这道题了。首先这道题不是一个 我们应该先缩点,把这个图变成一个 。
变成 就好了,我们就可以记录每个点的入度,答案即为所有入度为 的点的值的和(值就是这个点内的所有人被收买的数额中的最小值(不会被收买钱数为 ))。
#include <bits/stdc++.h>
#define int long long
using namespace std;
template<typename T>inline void read(T &FF){
T RR=1;FF=0;char CH=getchar();
for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
FF*=RR;
}
template<typename T>inline void write(T x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar('0'+x%10);
}
const int MAXN=1e6+10,MAXM=1e6+10;
int s[MAXN],stop,dfn[MAXN],low[MAXN],scccnt,sccnum[MAXN],dfscnt,tot,he[MAXN],ne[MAXM<<1],ed[MAXM<<1],n,x,y,de[MAXN],ans,m,k,dis[MAXN],num[MAXN],sum[MAXN];
void add(int x,int y){
ed[++tot]=y;
ne[tot]=he[x];
he[x]=tot;
}
inline void tarjan(int now){
dfn[now] = low[now] = ++dfscnt;
s[stop++] = now;
for (int i=he[now];i;i=ne[i]){
if(!dfn[ed[i]]){
tarjan(ed[i]);
low[now] = min(low[now], low[ed[i]]);
}else if(!sccnum[ed[i]]) {
low[now] = min(low[now], dfn[ed[i]]);
}
}
if(dfn[now]==low[now]){
scccnt++;
do{
sccnum[s[--stop]]=scccnt;
sum[scccnt]=min(sum[scccnt],dis[s[stop]]);//取min
}while(s[stop]!=now);
}
}//强联通分量
signed main(){
memset(sum,127,sizeof(sum));//赋上无穷大
memset(dis,127,sizeof(dis));//赋上无穷大
read(n);read(k);
for(int i=1;i<=k;i++)read(num[i]),read(dis[num[i]]);
read(m);
for(int i=1;i<=m;i++){
read(x);read(y);
add(x,y);
}
for(int i=1;i<=k;i++)
if(!dfn[num[i]])tarjan(num[i]);
for(int i=1;i<=n;i++)
if(!dfn[i])return cout<<"NO
"<<i,0;//可以被收买的点中不知道这个点的消息,即为不可以控制所有间谍
for(int i=1;i<=n;i++)
for(int j=he[i];j;j=ne[j])
if(sccnum[i]!=sccnum[ed[j]])de[sccnum[ed[j]]]++;
for(int i=1;i<=scccnt;i++)
if(!de[i])ans+=sum[i];
cout<<"YES
"<<ans;
return 0;
}