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<algorithm> 3 #include<iostream> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cstdio> 8 #include<queue> 9 #include<ctime> 10 #include<cmath> 11 #include<stack> 12 #include<map> 13 #include<set> 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<int>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<int>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 }
时间: 2024-10-06 08:03:40