zoukankan      html  css  js  c++  java
  • 1093: [ZJOI2007]最大半连通子图

                                                                       1093: [ZJOI2007]最大半连通子图

    Description

      一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
    两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,
    则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图
    中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
    ,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

    Input

      第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整
    数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤1
    00000, M ≤1000000;对于100%的数据, X ≤10^8

    Output

      应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

    Sample Input

    6 6 20070603
    1 2
    2 1
    1 3
    2 4
    5 6
    6 4

    Sample Output

    3
    3

    HINT

    Source

    第一遍做时 思路还是比较正确

    先tarjan缩点 再建新图 从入度为0的点跑 bfs 求最长链及条数 

    但是只有30分 因为我建完新图没有判重边 还有不知名的MLE和TLE (我也很绝望啊)

    后来才知道 这个新图内不能有重边 

    于是就 判重之后就拓扑排序 统计在这个点的半连通子图的点数和个数

      1 #include <queue>
      2 #include <cstdio>
      3 #include <cctype>
      4 
      5 const int MAXN=100010;
      6 
      7 int n,m,mod,id,inr,top,ans,total;
      8 
      9 int dfn[MAXN],low[MAXN],stack[MAXN],belong[MAXN],siz[MAXN],in[MAXN];
     10 
     11 int f[MAXN][2];
     12 
     13 bool vis[MAXN];
     14 
     15 struct node {
     16     int to;
     17     int next;
     18     node() {}
     19     node(int to,int next):to(to),next(next) {}
     20 };
     21 node e[MAXN*10],r[MAXN*10];
     22 
     23 int head[MAXN],tot,Head[MAXN],tal;
     24 
     25 inline void read(int&x) {
     26     int f=1;register char c=getchar();
     27     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
     28     for(;isdigit(c);x=x*10+c-48,c=getchar());
     29     x=x*f;
     30 }
     31 
     32 inline void add(int x,int y) {
     33     e[++tot]=node(y,head[x]);
     34     head[x]=tot;
     35 }
     36 
     37 inline int min(int a,int b) {return a<b?a:b;}
     38 
     39 inline bool pd(int u,int v) {
     40     for(int i=Head[u];i;i=r[i].next) 
     41       if(r[i].to==v) return true;
     42     return false;
     43 }
     44 
     45 void tarjan(int u) {
     46     dfn[u]=low[u]=++inr;
     47     stack[++top]=u;
     48     vis[u]=true;
     49     for(int i=head[u];i;i=e[i].next) {
     50         int v=e[i].to;
     51         if(!dfn[v]) {
     52             tarjan(v);
     53             low[u]=min(low[u],low[v]);
     54         }
     55         else if(vis[v]) low[u]=min(low[u],dfn[v]);
     56     }
     57     if(dfn[u]==low[u]) {
     58         ++id;
     59         int t;
     60         do {
     61             ++siz[id];
     62             t=stack[top--];
     63             vis[t]=false;
     64             belong[t]=id;
     65             vis[t]=false;
     66         }while(u!=t);
     67     }
     68 }
     69 
     70 int hh() {
     71     read(n);read(m);read(mod);
     72     for(int x,y,i=1;i<=m;++i) {
     73         read(x);read(y);
     74         add(x,y);
     75     }
     76     for(int i=1;i<=n;++i)
     77       if(!dfn[i]) tarjan(i);
     78     for(int i=1;i<=n;++i)
     79       for(int j=head[i];j;j=e[j].next) {
     80           int v=e[j].to;
     81           if(belong[i]!=belong[v]) {
     82               if(pd(belong[i],belong[v])) continue;
     83               ++in[belong[v]];
     84               r[++tal]=node(belong[v],Head[belong[i]]);
     85               Head[belong[i]]=tal;
     86           }
     87       }
     88     std::queue<int> q;
     89     for(int i=1;i<=id;++i) {
     90         f[i][0]=siz[i];f[i][1]=1;
     91         if(!in[i]) q.push(i);
     92     }
     93     while(!q.empty()) {
     94         int u=q.front();;
     95         q.pop();
     96         for(int i=Head[u];i;i=r[i].next) {
     97             int v=r[i].to;
     98             --in[v];
     99             if(!in[v]) q.push(v);
    100             if(f[v][0]<f[u][0]+siz[v]) f[v][0]=f[u][0]+siz[v],f[v][1]=f[u][1];
    101             else if(f[v][0]==f[u][0]+siz[v]) f[v][1]+=f[u][1],f[v][1]%=mod;
    102         }
    103     }
    104     for(int i=1;i<=id;++i) {
    105         if(f[i][0]>ans) ans=f[i][0],total=f[i][1];
    106         else if(f[i][0]==ans) total+=f[i][1],total%=mod;
    107     }
    108     printf("%d
    %d
    ",ans,total);
    109     return 0;
    110 }
    111 
    112 int sb=hh();
    113 int main (int argc,char**argv) {;}
    代码


    作者:乌鸦坐飞机
    出处:http://www.cnblogs.com/whistle13326/
    新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

     
  • 相关阅读:
    地址栏中提交中文参数乱码问题
    拼接html字符串时单引号问题
    细线表格的制作
    盒子模型
    盒子间距离的计算规则:
    正则表达式
    轻便+智能:史上最酷恒温器Nest 2.0!
    医疗的未来,是身体控制大权的争夺战
    而立之年话沧桑
    刘晓明大使在《电讯报》的英文原文
  • 原文地址:https://www.cnblogs.com/whistle13326/p/7490910.html
Copyright © 2011-2022 走看看