博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P2456 - 膜拜神犇
阅读量:7067 次
发布时间:2019-06-28

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

P2456 - 膜拜神犇

Description

有一个 n 个点 m 条边的有向图, 蒟蒻可以从 1 号点出发在图上走, 并且最终需要回到 1 号点。 每个点都有一个神犇( 包括 1 号点), 每次经过一个没到过的点, 蒟蒻都会膜拜那位 神犇。 蒟蒻希望膜拜尽可能多的神犇。

由于蒟蒻膜拜神犇的欲望非常强烈, 所以他可以有一次机会逆着一条有向边的方向走。 ( 需要注意的是, 这条边的方向不会改变)。
你现在想知道, 蒟蒻最多能膜拜多少神犇?

Input

第一行 2 个整数 n、 m, 分别表示图的点数和边数。

第 2 行到底 m+1 行, 每行两个整数 u,v, 描述一条 u 到 v 的有向边。

Output

一行一个整数表示蒟蒻最多能膜拜多少神犇。

Sample Input

7 10

1 2
3 1
2 5
2 4
3 7
3 5
3 6
6 5
7 2
4 7

Sample Output

6

Hint

数据范围:

对于 25%的数据, 保证 n<=100, m<=250,
对于 45%的数据, 保证 n<=3,000, m<=7,000。
对于 100%的数据, 保证 n,m<=100,000。

Source

图论

 

尽可能拜访尽量多的神犇,所以强连通分量缩点,变成了DAG,接下来,不存在环了,只存在从一个点到达另外一个点,走一条反向边,最回到一点,因此能不能回到1点,也就是反图能不能从1点出发到达这个点;同时,dis要尽量的大,因此spfa求最大值,枚举所有的点,与这个点相连的所有的边,就可以了;

 

1 /* QYP kuai wo dai ma*/  2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #define rep(i,a,b) for(register int i=a;i<=b;i++) 15 #define ll long long 16 #define re register 17 using namespace std; 18 const int N=100010; 19 struct Edge{ 20 int to,net; 21 }e1[N],e2[N],e[N]; 22 int h1[N],h2[N],num_e1,num_e2,n,m,num_e,head[N]; 23 int g[N],ans,a[N],b[N]; 24 inline int gi() { 25 re int res=0; 26 char ch=getchar(); 27 while(ch<'0'||ch>'9') ch=getchar(); 28 while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar(); 29 return res; 30 } 31 inline void add1(int x,int y) { 32 e1[++num_e1].to=y,e1[num_e1].net=h1[x],h1[x]=num_e1; 33 } 34 inline void add2(int x,int y) { 35 e2[++num_e2].to=y,e2[num_e2].net=h2[x],h2[x]=num_e2; 36 } 37 inline void add(int x,int y) { 38 e[++num_e].to=y,e[num_e].net=head[x],head[x]=num_e; 39 } 40 int low[N],dfn[N],dfs_clock,sccno[N],scc_cnt; 41 stack
S; 42 void Tarjan(int x) { 43 low[x]=dfn[x]=++dfs_clock; 44 S.push(x); 45 for(int i=head[x];i;i=e[i].net) { 46 int to=e[i].to; 47 if(!dfn[to]) { 48 Tarjan(to); 49 low[x]=min(low[x],low[to]); 50 } 51 else if(!sccno[to]) low[x]=min(low[x],dfn[to]); 52 } 53 if(low[x]==dfn[x]) { 54 ++scc_cnt; 55 int u; 56 for(;;) { 57 u=S.top();S.pop(); 58 sccno[u]=scc_cnt; 59 g[scc_cnt]++; 60 if(u==x) break; 61 } 62 } 63 } 64 void SUO() { 65 rep(i,1,n) if(!dfn[i]) Tarjan(i); 66 for(int x=1;x<=n;x++) 67 for(int i=head[x];i;i=e[i].net) { 68 int to=e[i].to; 69 if(sccno[to]!=sccno[x]) { 70 add1(sccno[x],sccno[to]),add2(sccno[to],sccno[x]); 71 } 72 } 73 } 74 bool inq[N]; 75 void spfa(int ss,int hh[],Edge ee[],int dis[]) { 76 memset(inq,0,sizeof(inq)); 77 queue
q; 78 dis[ss]=g[ss]; 79 q.push(ss);inq[ss]=1; 80 while(!q.empty()) { 81 int u=q.front();q.pop(); 82 inq[u]=0; 83 for(int i=hh[u];i;i=ee[i].net) { 84 int to=ee[i].to; 85 if(dis[to] < dis[u] + g[to]) { 86 dis[to]=dis[u]+g[to]; 87 if(!inq[to]) q.push(to),inq[to]=1; 88 } 89 } 90 } 91 } 92 int main() { 93 freopen("OrzOrz.in","r",stdin); 94 freopen("OrzOrz.out","w",stdout); 95 n=gi(),m=gi(); 96 rep(i,1,m) { 97 re int u=gi(),v=gi(); 98 add(u,v); 99 }100 SUO();101 spfa(sccno[1],h1,e1,a);102 spfa(sccno[1],h2,e2,b);103 for(int x=1;x<=scc_cnt;x++) {104 for(int i=h1[x];i;i=e1[i].net) {105 int to=e1[i].to;106 if(a[to]&&b[x]) ans=max(ans,a[to]+b[x]);107 }108 }109 if(ans==g[sccno[1]])110 printf("%d ",ans);111 else 112 printf("%d",ans-g[sccno[1]]);113 return 0;114 }

 

 

 

转载于:https://www.cnblogs.com/ypz999/p/6818832.html

你可能感兴趣的文章
7.2.7、数组指针的操作
查看>>
SetProp()、GetProp()、RemoveProp() API接口
查看>>
ES6 module模块
查看>>
content management system
查看>>
缓存穿透 缓存雪崩
查看>>
System.gc
查看>>
最小二乘法多项式曲线拟合原理与实现(转)
查看>>
Java NIO 系列教程(转)
查看>>
socketio
查看>>
Oracle的常见错误及解决办法
查看>>
一花一世界(转)
查看>>
winform 控件部分
查看>>
BZOJ1066 蜥蜴
查看>>
(三)控制浏览器操作
查看>>
进程控制编程
查看>>
Postgresql 数据库,如何进行数据备份以及导入到另外的数据库
查看>>
python之闭包、装饰器
查看>>
实现单例模式的9个方法
查看>>
Java的接口总结
查看>>
C++复习
查看>>