题目描述

由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。

我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。

请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。

输入输出格式

输入格式:
第一行只有一个整数n。

第二行是整数p。表示愿意被收买的人数,1≤p≤n。

接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。这个数额不超过20000。

紧跟着一行只有一个整数r,1≤r≤8000。然后r行,每行两个正整数,表示数对(A, B),A间谍掌握B间谍的证据。

输出格式:
如果可以控制所有间谍,第一行输出YES,并在第二行输出所需要支付的贿金最小值。否则输出NO,并在第二行输出不能控制的间谍中,编号最小的间谍编号。

输入输出样例

输入样例#1:
3
2
1 10
2 100
2
1 3
2 3
输出样例#1:
YES
110
输入样例#2:
4
2
1 100
4 200
2
1 2
3 4
输出样例#2:
NO
3

说明

懒得多说直接上代码了。

#include<bits/stdc++.h>
using namespace std;
inline int read()
{int x=0; char c=getchar();while(!isdigit(c)) c=getchar();for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x;
}
int n,p,r,pat,top,tim,ans;
//pat表示边数,part表示强连通分量数,top表示栈高,tim表示时间戳
int mon[3100];
//money
int blg[3100],fa[3100];
//belong、father(其实两者本质是一样的,关于father等会儿会讲)
int dfn[3100],low[3100];
//深度优先(英文)、lowest(应该是吧)
int stk[3100],head[3100];
//stack(栈)、head是邻接链表的头(其实我觉得更像是尾)
bool instk[3100];
//instack表示是否在栈里面
struct tpat
{int v,next;
}edge[8100];void add(int u,int v)
{edge[pat].next=head[u];edge[pat].v=v;head[u]=pat++;
} //邻接表存边( 比向量vector的push_back()要快 ) void tarjan(int u)   //tarjan缩点不详解,自行百度
{dfn[u]=low[u]=++tim;instk[u]=true; stk[++top]=u;for(int i=head[u];i!=-1;i=edge[i].next) //遍历点u的邻接表 {int v=edge[i].v;if(!dfn[v])tarjan(v),low[u]=min(low[u] , low[v]);else if(instk[v]) //这点很重要!被搜到过但不在栈内的话就不能操作 low[u]=min(low[u] , dfn[v]);}if(dfn[u]==low[u]) //low无变化代表u是一个强连通分量的出发点 {int j;do{j=stk[top--];//从栈顶一直弹弹弹(弹走鱼尾纹),弹到u点(当前点) mon[u]=min(mon[u] , mon[j]);instk[j]=false; //出栈 blg[j]=u;//注意这里就是把belong[j]赋值为u了,方便缩点后的操作 }while(j!=u);  //弹到当前节点就退出 }
}void solve()
{for(int i=1;i<=n;++i) //fa[i]都赋为本身 fa[i]=i;for(int i=1;i<=n;++i)for(int j=head[i];j!=-1;j=edge[j].next)if(blg[i]!=blg[edge[j].v]) fa[blg[edge[j].v]]=blg[i];//这里是不能把fa换成blg的,举个例子吧,
//如果只有三个点,然后有两条边使两个不同的点分别指向同一个点的话...
//想必你也猜到了,我也栽在这儿过~~~  _(:з」∠)_ for(int i=1;i<=n;++i){if(blg[i]!=i || fa[i]!=i)  //不是必须要付费的间谍就continue continue; if(mon[i]==0x3f3f3f3f)  //如果说这个点无穷大就直接输出+退出//话说我怎么觉得这里是有bug的来着?貌似我自己都能把自己hack掉...//额...不过洛谷上是水过去了... _(:з」∠)_ 下文再放个图试试? {printf("NO\n%d\n",i);return ; //输完直接退 }ans+=mon[i]; //否则答案累加 }printf("YES\n%d\n",ans);
}int main()
{n=read();p=read();memset(mon,0x3f,sizeof(mon));memset(head,-1,sizeof(head));for(int i=0;i<p;++i)mon[read()]=read();r=read();for(int i=0;i<r;++i){ int u=read(),v=read(); add(u,v); }for(int i=1;i<=n;++i) //缩点 if(!dfn[i])tarjan(i);solve();    //缩点完开始正式工作 return 0;
}

(看我注解写的多认真,你能忍心不点个赞吗? _ (:з」∠)_ )

然后我来说说我是怎么hack掉自己的程序的 … -_-|| (方便起见,假设没有一个间谍能被收买)

然后这就hack了?洛谷上还水过去了?心中一万匹草泥马在奔腾

然后呢?标程在哪里?

然我先想想…emmm好了上代码吧!

其实…只要把solve函数改成这样就好了:

#include<bits/stdc++.h>
using namespace std;
inline int read()
{int x=0; char c=getchar();while(!isdigit(c)) c=getchar();for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x;
}
int n,p,r,pat,top,tim,ans;
int mon[3100],mnode[3100];
//多开了一个mnode表示:如果该点是其所在的强连通分量的出发点,则该强连通分量中最小的点的编号
int blg[3100],fa[3100];
int dfn[3100],low[3100];
int stk[3100],head[3100];
bool instk[3100];
struct tpat
{int v,next;
}edge[8100];void add(int u,int v)
{edge[pat].next=head[u];edge[pat].v=v;head[u]=pat++;
} void tarjan(int u)
{dfn[u]=low[u]=++tim;instk[u]=true; stk[++top]=u;for(int i=head[u];i!=-1;i=edge[i].next) {int v=edge[i].v;if(!dfn[v])tarjan(v),low[u]=min(low[u] , low[v]);else if(instk[v]) low[u]=min(low[u] , dfn[v]);}if(dfn[u]==low[u]) //low无变化代表u是一个强连通分量的出发点 {int j;do{j=stk[top--];//从栈顶一直弹弹弹(弹走鱼尾纹),弹到u点(当前点) mon[u]=min(mon[u] , mon[j]);instk[j]=false; //出栈 blg[j]=u;if(mnode[j]==4000 || mnode[u]==4000)//如果强连通分量中有人可以收买,则整个强连通分量中的人都可以被控制mnode[u]=4000;else mnode[u]=min(mnode[u] , mnode[j]);}while(j!=u);}
}void solve()
{for(int i=1;i<=n;++i)for(int j=head[i];j!=-1;j=edge[j].next)if(blg[i]!=blg[edge[j].v])fa[blg[edge[j].v]]=blg[i];for(int i=1;i<=n;++i){if(blg[i]==i)mnode[fa[i]]=min(mnode[fa[i]] , mnode[i]);//这里的意思是在某个强连通分量的出发点时将改点前驱的强连通分量的出发点取编号为min的操作if(blg[i]!=i || fa[i]!=i)continue;if(mon[i]==0x3f3f3f3f){printf("NO\n%d\n",mnode[i]); //然后这里输出就变成了当前点的最小编号return ;}ans+=mon[i];}printf("YES\n%d\n",ans);
}int main()
{n=read();p=read();memset(mon,0x3f,sizeof(mon));memset(head,-1,sizeof(head));for(int i=0;i<p;++i)mon[read()]=read();r=read();for(int i=0;i<r;++i){ int u=read(),v=read(); add(u,v); }for(int i=1;i<=n;++i){ mnode[i]=fa[i]=i ; if(mon[i]!=0x3f3f3f3f) mnode[i]=4000; }//可以收买的就直接为最大4000for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);solve();return 0;
}

珍惜无语,洛谷数据是真水啊,圣水!(再吐槽一波)

OK,本篇blog的正文到此结束,然后我是无力吐槽了,累得要死 _ (:з」∠) _
各位看官们下次见!

转载于:https://www.cnblogs.com/Judge/p/9383039.html

P1262 间谍网络 (tarjan缩点 水过去)相关推荐

  1. 洛谷1262 间谍网络 tarjan缩点

    题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B.有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报 ...

  2. 洛谷P1262 间谍网络题解

    洛谷P1262 间谍网络题解 题目大意 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果 A 间谍手中掌握着关于 B 间谍的犯罪证据,则称 A 可以揭发 B.有些间谍收受贿赂,只要 ...

  3. P1262 间谍网络

    传送门 思路: ①在 Tarjan 的基础上加一个 belong 记录每个点属于哪个强连通分量. ②存图完成后,暴力地遍历全图,查找是否要间谍不愿受贿. inline void dfs(int u) ...

  4. Luogu P1262 间谍网络 【强连通分量/缩点】By cellur925

    题目传送门 真是一道好题呀~~~~qwq 知道这题是tarjan,但是想了很久怎么用上强连通分量.因为样例们...它显然并不是一个强联通分量! (被样例迷惑的最好例子) 然后...就没有然后了...感 ...

  5. P1262 间谍网络 (Tarjan 求强连通分量)

    题目传送门:https://www.luogu.com.cn/problem/P1262 题意 题意转换成图的角度理解,给出初始可以访问的节点 D i D_i Di​ 以及访问这些节点需要的代价 W ...

  6. loj #10095 P1262 间谍网络

    analysis 首先将题面简化,问题就成为:给一个有向图,有一些特殊点有权值,其他点都没有权值,选取特殊点中的一部分使得其权值和最小且其与其相连的点构成的集合等价于所有点构成的集合(语文差,没办法) ...

  7. 洛谷P1262 间谍网络

    传送门 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果 A 间谍手中掌握着关于 B 间谍的犯罪证据,则称 A 可以揭发 B.有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意 ...

  8. P1262_美帝的间谍网络被我部捕获!

    题面 这道题太神了吧,从昨晚七点半做到今天下午两点. 我经历了以下折腾(以下内容可跳过): 一开始想的是用Tarjan缩点,然后以可以被收买的间谍为起点跑最短路,通过路径染色,让一条路径上的点的权值等 ...

  9. 缩点【洛谷P1262】 间谍网络

    [洛谷P1262] 间谍网络 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B.有些间谍收受贿赂,只要给他们一定数量的美元,他 ...

最新文章

  1. Dissecting BERT Part 1: The Encoder 解析BERT解码器(transformer)
  2. JAVA WEB新进展
  3. 【学习】SpringBoot之自定义拦截器
  4. Python中re.sub()实现替换文本字符串
  5. 初试WebStorage之localstorage
  6. Pandas中的 transform() 结合 groupby() 用法示例
  7. java条件执行方法_java 开启多线程里面如何加条件判断执行其他逻辑?
  8. 一维和二维卷积和池化
  9. 量化策略回测TRIXKDJ
  10. latex Label ‘ ‘ multiply defined
  11. canvas浅谈 实现简单的自旋转下落
  12. 统计学习方法读书笔记14-逻辑斯蒂回归代码实现与最大熵代码实现
  13. Ubuntu中安装ns3
  14. 最新服务器cpu14纳米,Intel CPU处理器路线图:14nm用到2021年 7nm再等3年
  15. 如何利用任意波形发生器创建你想要的波形并输出
  16. ESP32学习笔记(18)——光强度GY-30(BH1750)使用
  17. 乌隆他尼皇家大学-静待绽放的“明珠”
  18. ASP网页与HTML网页的区别是什么
  19. 数据化运营chapter4_code--分析模型和方法
  20. 计算机视觉论文-2021-07-23

热门文章

  1. git pull keeping local changes
  2. Make Fcitx Work In Sublime-Text-3
  3. DE14 Interpretation of the Exceptional Case: Resonance
  4. 22解析函数的级数表示(一)
  5. 3D数学之柏林噪声(Perlin Noise)
  6. 基于深度卷积神经网络的苹果叶片植物病理学疾病检测
  7. AI学习笔记(十四)CNN之图像分割
  8. Datawhale 零基础入门数据挖掘-Task3 特征工程
  9. 机器学习应用量化投资没啥用?那是你方法不对!
  10. 职业学校计算机教师履职总结,中等职业学校骨干教师(计算机应用专业)省级培训 总结...