博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P1262 间谍网络
阅读量:4519 次
发布时间:2019-06-08

本文共 2621 字,大约阅读时间需要 8 分钟。

思路:

  ①在 Tarjan 的基础上加一个 belong 记录每个点属于哪个强连通分量。

  ②存图完成后,暴力地遍历全图,查找是否要间谍不愿受贿。

inline void dfs(int u){    if(vis[u]) return ;    vis[u]=true,tot++;    for(int i=head[u];i;i=t[i].nex)        dfs(t[i].to);}//遍历

  遍历完后,看看那个间谍没被搜索过(vis数组记录),就把那个不受贿的间谍抓出来。

  ③如果所有的间谍都愿意受贿,就继续。可以开一个smon数组,记录每个强连通分量中间谍愿意受贿的最小的钱数。结合belong数组(因为一个强连通分量只要让一个间谍受贿,就能拖出这个强连通分量中所有的间谍。),用ans记录所需总的钱数,输出。

AC代码: 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;#define maxn 3001#define maxm 9000000#define INF 0x3f3f3f3fint n,m,cnt,tot,dfn[maxn],low[maxn],sta[maxn],belong[maxn],rd[maxn],smon[maxn],mon[maxn];//belong记录每个点属于哪个强连通分量,rd记录每个点的入度,smon记录间谍网络中每个连通块的最小受贿的钱,mon记录每个间谍的受贿所需的钱 bool vis[maxn];struct hh{ int nex,to;}t[maxm];int tto=0,head[maxm];//链式前向星inline void add(int nex,int to){ t[++tto].nex=head[nex]; t[tto].to=to; head[nex]=tto;}//存图部分inline void dfs(int u){ if(vis[u]) return ; vis[u]=true,tot++; for(int i=head[u];i;i=t[i].nex) dfs(t[i].to);}//遍历初始图inline int read(){ char kr=0; char ls; for(;ls>'9'||ls<'0';kr=ls,ls=getchar()); int xs=0; for(;ls>='0'&&ls<='9';ls=getchar()) { xs=xs*10+ls-48; } if(kr=='-') xs=0-xs; return xs;}//快读 inline void tarjan(int u)//tarjan的模板 { dfn[u]=low[u]=++tot; vis[u]=true; sta[++cnt]=u; for(int i=head[u];i;i=t[i].nex) { int v=t[i].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) { low[u]=min(low[u],dfn[v]); } }//日常操作 if(dfn[u]==low[u]) { smon[u]=INF; do { vis[sta[cnt]]=false; belong[sta[cnt]]=u; smon[u]=min(smon[u],mon[sta[cnt]]);//取连通块中间谍受贿的最小值,更新smon cnt--; }while(sta[cnt+1]!=u); }}int main(){ n=read();m=read(); for(int i=1;i<=n;i++) mon[i]=INF;//不受贿的间谍设为一个极大值 for(int i=1;i<=m;i++) { int x,y; x=read();y=read(); mon[x]=y;//读入受贿间谍要的钱 } m=read(); for(int i=1;i<=m;i++) { int x,y; x=read();y=read(); add(x,y);//加边存图 } for(int i=1;i<=n;i++) if(mon[i]!=INF) dfs(i);//遍历全图,确定是否有间谍不愿被收买 for(int i=1;i<=n;i++) { if(!vis[i])//找到那个不愿被收买的间谍 { printf("NO\n%d",i); return 0;//直接结束程序 } } tot=0; for(int i=1;i<=n;i++) vis[i]=0;//初始化vis for(int i=1;i<=n;i++) if(mon[i]!=INF && !dfn[i]) tarjan(i);//tarjan记录强连通分量数,及每个强连通分量的smon for(int i=1;i<=n;i++) { for(int j=head[i];j;j=t[j].nex) { if(belong[i]!=belong[t[j].to]) rd[belong[t[j].to]]++;//统计每个强连通分量的入度 (找入度为0的点) } } int ans=0; for(int i=1;i<=n;i++) if(belong[i]==i && !rd[i]) ans+=smon[i];//入度为0的点,即为连通块的起点,且smon已经被更新,直接加入答案 printf("YES\n%d",ans);//输出 return 0;}

其实也没有想象中的那么暴力,手写栈+inline后,最慢的一个点都只用了4ms。

转载于:https://www.cnblogs.com/lck-lck/p/9630592.html

你可能感兴趣的文章
阿里巴巴卖空阿里巴巴入股新浪微博抑制投资者卖空行为
查看>>
分析打开hdu 3335 (最小路径覆盖)
查看>>
添加源ubuntu_x64 安装 Adobe Reader
查看>>
NFS-heartbeat-drbd模拟NFS高可用
查看>>
SQL Server性能调优:资源管理之内存管理篇(上)
查看>>
javaScript 基础知识
查看>>
接近开关,光耦
查看>>
基于visual Studio2013解决C语言竞赛题之1033数字交换
查看>>
给datalist加自动编号(解决博客的第XX楼)
查看>>
BZOJ3282: Tree (LCT模板)
查看>>
ES6中变量的解构赋值
查看>>
编译器C-Free V352注册算法分析
查看>>
数据绑定控件Reperter
查看>>
【codeforces】【比赛题解】#937 CF Round #467 (Div. 2)
查看>>
剑指Offer学习笔记(3)——解决面试题的思路
查看>>
.NET Framework基础知识(二)(转载)
查看>>
Yii DataProvider
查看>>
BestCoder Round #14 B 称号 Harry And Dig Machine 【TSP】
查看>>
hdu 1114 Piggy-Bank
查看>>
maven集成tomcat插件启动报错
查看>>