P1262 间谍网络 (tarjan缩点 水过去)
题目描述
由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果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; }
//可以收买的就直接为最大4000
for(int i=1;i<=n;++i)
if(!dfn[i])
tarjan(i);
solve();
return 0;
}
珍惜无语,洛谷数据是真水啊,圣水!(再吐槽一波)
OK,本篇blog的正文到此结束,然后我是无力吐槽了,累得要死 _ (:з」∠) _
各位看官们下次见!
P1262 间谍网络 (tarjan缩点 水过去)的更多相关文章
- Luogu P2002 消息扩散&&P1262 间谍网络
怕自己太久没写Tarjan了就会把这种神仙算法忘掉. 其实这种类型的图论题的套路还是比较简单且显然的. P2002 消息扩散 很显然的题目,因为在一个环(其实就是强连通分量)中的城市都只需要让其中一个 ...
- 洛谷——P1262 间谍网络
P1262 间谍网络 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B.有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意 ...
- 洛谷 P1262 间谍网络 —— 缩点
题目:https://www.luogu.org/problemnew/show/P1262 首先,一个强连通分量里有一个点被控制则所有点都被控制,所以先 tarjan 缩点,记一下每个连通块中能被收 ...
- tyvj 1153 间谍网络 tarjan有向图强连通
P1153 - 间谍网络 From ForeverBell Normal (OI)总时限:13s 内存限制:128MB 代码长度限制:64KB 描述 Description 由于外国 ...
- P1262 间谍网络
传送门 思路: ①在 Tarjan 的基础上加一个 belong 记录每个点属于哪个强连通分量. ②存图完成后,暴力地遍历全图,查找是否要间谍不愿受贿. inline void dfs(int u) ...
- luogu P1262 间谍网络
嘟嘟嘟 建图还是很明显的. 接着分两种情况: 1.图中不存在环:那么只要收买那些入度为0的点.如果这些点有的不能收买.就不能控制所有间谍. 2.图中存在环,那么对于这些在环中的点,我们只要收买数额最少 ...
- 【luogu P1262 间谍网络】 题解
题目链接:https://www.luogu.org/problemnew/show/P1262 注意: 1.缩点时计算出入度是在缩完点的图上用color计算.不要在原来的点上计算. 2.枚举出入度时 ...
- 洛谷 P1262 间谍网络==Codevs 4093 EZ的间谍网络
4093 EZ的间谍网络 时间限制: 10 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B ...
- 洛谷 1262 间谍网络 Tarjan 图论
洛谷 1262 图论 tarjan 并不感觉把这道题目放在图的遍历中很合适,虽然思路比较简单但是代码还是有点多的,, 将可收买的间谍的cost值设为它的价格,不可购买的设为inf,按照控制关系连图,T ...
随机推荐
- 阿里云MongoDB存储数据
近期上了个活动,考虑后期的运维及人力成本,还是选择了阿里云的MongoDB,不过阿里云这玩意本地测试官方没有给本地测试链接地址,只能做映射上去了测了... 选了个2核4G的,更多详细信息,可以去阿里上 ...
- 无法推动项目起步?Let's try McDonald’s Theory
McDonald’s Theory I use a trick with co-workers when we’re trying to decide where to eat for lunch a ...
- Spring boot 工具类静态属性注入及多环境配置
由于需要访问MongoDB,但是本地开发环境不能直接连接MongoDB,需要通过SecureCRT使用127.0.0.2本地IP代理.但是程序部署到线上生产环境后,是可以直接访问MongoDB的,因此 ...
- Asp.Net 初级 高级 学习笔记
01.Main函数是什么?在程序中使用Main函数有什么需要注意的地方?02.CLR是什么?程序集是什么?当运行一个程序集的时候,CLR做了什么事情?03.值类型的默认值是什么?(情况一:字段或全局静 ...
- 卷积中的full、same、valid
通常用外部api进行卷积的时候,会面临mode选择. 本文清晰展示三种模式的不同之处,其实这三种不同模式是对卷积核移动范围的不同限制. 设 image的大小是7x7,filter的大小是3x3 ...
- windows 下使用 sc 添加创建exe服务;
SC 是用于与服务控制管理器和服务进行通信的命令行程序. 1.SC 命令 格式 sc <server> [command] [service name] <option1> & ...
- Java SE之网络编程:知识框架
- rabbitMQ学习3-RPC远程过程调用
将一个函数运行在远程计算机上并且等待获取那里的结果,这个称作远程过程调用(Remote Procedure Call)或者 RPC. RPC是一个计算机通信协议. 比喻 将计算机服务运行理解为厨师做饭 ...
- iTOP-6818开发板支持AXP228电源管理[官方推荐最佳匹配]_支持动态调频
iTOP-6818开发板与4418开发板共兼容同一底板: 核心板:::::: 尺寸 50mm*60mm 高度 核心板连接器组合高度1.5mm PCB层数 6层PCB沉金设计 4418 CPU ARM ...
- 第25月第15天 udacity cs253
1.cs253 https://classroom.udacity.com/courses/cs253 webapp2 Install WebOb, Paste and webapp2¶ We nee ...