• zjoi 2007 semi 最大半连通子图 强连通分量 动态规划


    题意:一个有向图称为半连通的(Semi-Connected),如果满足:

    ,即对于图中任意两点u,v, 存在一条uv的有向路径或者从vu的有向路径。 

    若满足,则称G’是G的一个导出子图。

    G’G的导出子图,且G’半连通,则称G’G的半连通子图。

    G’G所有半连通子图中包含节点数最多的,则称G’G的最大半连通子图。

    给定一个有向图G,请求出G的最大半连通子图拥有的节点数K,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出CX的余数。

    思路:强连通分量缩点 DP

      1 #include<iostream>
    2 #include<cstdio>
    3 #include<cmath>
    4 #include<cstring>
    5 #include<ctime>
    6 using namespace std;
    7 #define MAXN 100011
    8 #define MAXM 4000011
    9 struct node
    10 {
    11 int num;
    12 node *next;
    13 };
    14 int finish[MAXN],mark[MAXN],dp[MAXN],num[MAXN],sum[MAXN];
    15 node *graph[MAXN],*grapht[MAXN],*graphnew[MAXN],*map[MAXN];
    16 node memo[MAXM];
    17 bool use[MAXN];
    18 int top,color,mod,t=0;
    19 int n,m;
    20 void add(int x,int y,node *graph[])
    21 {
    22 node *p=&memo[top++];
    23 p->num=y; p->next=graph[x]; graph[x]=p;
    24 }
    25 void dfs(int i)
    26 {
    27 use[i]=1;
    28 for(node *p=graph[i];p;p=p->next)
    29 if(!use[p->num]) dfs(p->num);
    30 finish[++t]=i;
    31 }
    32 void dfst(int i)
    33 {
    34 use[i]=1;
    35 mark[i]=color;
    36 add(color,i,map);
    37 sum[color]++;
    38 for(node *p=grapht[i];p;p=p->next)
    39 if(!use[p->num]) dfst(p->num);
    40 }
    41 void connect()
    42 {
    43 int i;
    44 memset(use,0,sizeof(use));
    45 for(i=1;i<=n;i++)
    46 if(!use[i]) dfs(i);
    47 memset(use,0,sizeof(use));
    48 for(i=n;i>0;i--)
    49 if(!use[finish[i]])
    50 {
    51 color++;
    52 dfst(finish[i]);
    53 }
    54 }
    55 void reduce()
    56 {
    57 memset(use,0,sizeof(use));
    58 int i;
    59 int u,v;
    60 for(i=1;i<=color;i++)
    61 {
    62 u=i;
    63 for(node *t=map[i];t;t=t->next)
    64 for(node *p=graph[t->num];p;p=p->next)
    65 {
    66 v=mark[p->num];
    67 if(u==v) continue;
    68 if(!use[v])
    69 {
    70 use[v]=1;
    71 add(u,v,graphnew);
    72 }
    73 }
    74 for(node *t=map[i];t;t=t->next)
    75 for(node *p=graph[t->num];p;p=p->next)
    76 use[mark[p->num]]=0;
    77 }
    78 }
    79 void dynamic()
    80 {
    81 int i;
    82 for(i=1;i<=color;i++)
    83 {
    84 dp[i]=sum[i]; num[i]=0;
    85 }
    86 int ans=0,ans_num=0;
    87 for(i=1;i<=color;i++)
    88 {
    89 if(dp[i]==sum[i]) num[i]=1;
    90 if(dp[i]>ans) ans=dp[i];
    91 for(node *p=graphnew[i];p;p=p->next)
    92 {
    93 if(dp[i]+sum[p->num]>dp[p->num])
    94 dp[p->num]=dp[i]+sum[p->num];
    95 }
    96 }
    97 printf("%d\n",ans);
    98 for(i=1;i<=color;i++)
    99 {
    100 for(node *p=graphnew[i];p;p=p->next)
    101 {
    102 if(dp[i]+sum[p->num]==dp[p->num])
    103 num[p->num]=(num[i]+num[p->num])%mod;
    104 }
    105 if(ans==dp[i]) ans_num=(num[i]+ans_num)%mod;
    106 }
    107 printf("%d\n",ans_num);
    108 }
    109
    110 int main()
    111 {
    112 freopen("semi.in","r",stdin);
    113 freopen("semi.out","w",stdout);
    114 top=color=0;
    115 memset(map,0,sizeof(map));
    116 memset(sum,0,sizeof(sum));
    117 memset(graph,0,sizeof(graph));
    118 memset(grapht,0,sizeof(grapht));
    119 memset(graphnew,0,sizeof(graphnew));
    120 scanf("%d%d%d",&n,&m,&mod);
    121 node *p;
    122 int i;
    123 int x,y;
    124 for(i=1;i<=m;i++)
    125 {
    126 scanf("%d%d",&x,&y);
    127 add(x,y,graph); add(y,x,grapht);
    128 }
    129 connect();
    130 reduce();
    131 dynamic();
    132 return 0;
    133 }



  • 相关阅读:
    献给所有学习控件和组件开发的读者
    ASP.NET 2.0书稿最新进展——开始一审
    愿我们共同进步——献给《Programming ASP.NET 3rd. 中文版》
    Error from MSDN——No4. Login.UserName
    安装MSDN中文版后的乱弹
    Error from MSDN——No9. Login.UserNameRequiredErrorMessage
    Error from MSDN——No1. Roles.Enabled
    Error from MSDN——No8. Login.PasswordRequiredErrorMessage
    热心的朋友请注意:ASP.NET 2.0书稿目录征求意见
    撰写《ASP.NET 2.0开发指南》的非正式小结
  • 原文地址:https://www.cnblogs.com/myoi/p/2418685.html
Copyright © 2020-2023  润新知