zoukankan      html  css  js  c++  java
  • P2456

    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 }
  • 相关阅读:
    android 内存泄漏分析
    sublime text3
    Bind Service 不会在后台无限期的一直运行
    uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型?
    #include < >与#include “ ”
    什么是库?
    gcc编译器
    如何写C语言程序
    ubuntu登陆root用户验证失败
    nginx location匹配顺序及CI框架的nginx配置
  • 原文地址:https://www.cnblogs.com/ypz999/p/6818832.html
Copyright © 2011-2022 走看看