zoukankan      html  css  js  c++  java
  • UVA11324 强连通+dp记忆化搜索

    题意:对于一个有向图,问最大团中有多少点,要求该点集内所有点对间至少有一条路径(u到v或v到u或两条都有)。

    首先,对于每一个强连通分量,其中的所有点必然能够互相到达,所以先进行缩点,然后对于缩点后的 DAG,dp[i] 表示从 i 强连通分量开始能够到达的最多的点数,那么在缩点时需要记录一下每个强连通分量的点数。然后进行DP,初始值定为该强连通分量的点数,然后用它能到达的点来更新它本身。取最大值就行了。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stack>
     4 #include<queue>
     5 using namespace std;
     6 
     7 const int maxn=1005;
     8 const int maxm=50005;
     9 
    10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];
    11 int n,t,scccnt;
    12 int stx[maxn],low[maxn],scc[maxn],num[maxn],dp[maxn];
    13 stack<int>S;
    14 
    15 void init(){
    16     memset(head,-1,sizeof(head));
    17     size[0]=size[1]=0;
    18     memset(dp,0,sizeof(dp));
    19 }
    20 
    21 void add(int a,int b,int c=0){
    22     point[c][size[c]]=b;
    23     nxt[c][size[c]]=head[c][a];
    24     head[c][a]=size[c]++;
    25 }
    26 
    27 void dfs(int s){
    28     stx[s]=low[s]=++t;
    29     S.push(s);
    30     for(int i=head[0][s];~i;i=nxt[0][i]){
    31         int j=point[0][i];
    32         if(!stx[j]){
    33             dfs(j);
    34             low[s]=min(low[s],low[j]);
    35         }
    36         else if(!scc[j]){
    37             low[s]=min(low[s],stx[j]);
    38         }
    39     }
    40     if(low[s]==stx[s]){
    41         scccnt++;
    42         while(1){
    43             int u=S.top();S.pop();
    44             scc[u]=scccnt;
    45             num[scccnt]++;
    46             if(s==u)break;
    47         }
    48     }
    49 }
    50 
    51 void setscc(){
    52     memset(stx,0,sizeof(stx));
    53     memset(scc,0,sizeof(scc));
    54     memset(num,0,sizeof(num));
    55     t=scccnt=0;
    56     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
    57     for(int i=1;i<=n;++i){
    58         for(int j=head[0][i];~j;j=nxt[0][j]){
    59             int k=point[0][j];
    60             if(scc[i]!=scc[k]){
    61                 add(scc[i],scc[k],1);
    62             }
    63         }
    64     }
    65 }
    66 
    67 void dfs1(int s){
    68     if(dp[s])return;
    69     dp[s]=num[s];
    70     for(int i=head[1][s];~i;i=nxt[1][i]){
    71         int j=point[1][i];
    72         dfs(j);
    73         if(num[s]+dp[j]>dp[s])dp[s]=num[s]+dp[j];
    74     }
    75 }
    76 
    77 int main(){
    78     int T;
    79     scanf("%d",&T);
    80     while(T--){
    81         int m;
    82         scanf("%d%d",&n,&m);
    83         init();
    84         while(m--){
    85             int a,b;
    86             scanf("%d%d",&a,&b);
    87             add(a,b);
    88         }
    89         setscc();
    90         int ans=0;
    91         for(int i=1;i<=scccnt;++i){
    92             dfs1(i);
    93             if(ans<dp[i])ans=dp[i];
    94         }
    95         printf("%d
    ",ans);
    96     }
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    前端知识点--CSS overflow 属性
    js排序——sort()排序用法
    vue知识点---element el-date-picker 插件默认时间属性default-value怎么赋值?
    vue知识点----element UI+vue关于日期范围选择的操作,picker-options属性的使用
    JS_点击事件_弹出窗口_自动消失
    Echarts +ajax+JSONPObject 实现后台数据图表化
    Floyd弗洛伊德算法
    线程中join方法和Sleep方法的举例
    循环注册十个账号,保证程序重启之后,使用这十个账号都能登录成功
    替换文本文件内容
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4799160.html
Copyright © 2011-2022 走看看