• UVa 11234 The Largest Clique


    找最长的连接的点的数量。用tarjan缩点,思考可知每一个强连通分量里的点要么都选,要么都不选(走别的路),可以动规解决。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<cstring>
     6 using namespace std;
     7 const int mxn=12000;
     8 int top,stack[mxn];
     9 bool inst[mxn];
    10 int cnt,dnow; 
    11 int dfn[mxn],low[mxn];
    12 int belone[mxn];
    13 int ptcnt[mxn];
    14 int dp[mxn];
    15 vector<int> e[mxn];//邻接表 
    16 vector<int> pt[mxn];//缩点后的点集 
    17 void clear(){
    18     cnt=0;dnow=0;top=0;
    19     memset(dfn,-1,sizeof(dfn));
    20     memset(inst,false,sizeof(inst));
    21     memset(dp,0,sizeof dp);
    22     memset(ptcnt,0,sizeof ptcnt);
    23     memset(belone,0,sizeof belone);
    24     for(int i=1;i<mxn;i++) e[i].clear();
    25     for(int i=1;i<mxn;i++) pt[i].clear();
    26 }
    27 int n,m;
    28 void tarjan(int s){
    29     int v=0,i;
    30     dfn[s]=++dnow;
    31     low[s]=dfn[s];
    32     inst[s]=true; 
    33     stack[++top]=s;
    34     int si=e[s].size();
    35     for(i=0;i<si;i++){
    36         v=e[s][i];
    37         if(dfn[v]==-1){
    38             tarjan(v);
    39             low[s]=min(low[v],low[s]);
    40         }
    41         else if(inst[v]){
    42             low[s]=min(dfn[v],low[s]);
    43         }
    44     }
    45     if(dfn[s]==low[s]){
    46         cnt++;
    47         do{
    48             v=stack[top--];
    49             belone[v]=cnt;
    50             inst[v]=false;
    51         }while(s!=v);
    52     }
    53     return;
    54 }
    55 int find(int x){//动规 
    56     if(pt[x].size()==0)return dp[x]=ptcnt[x];
    57     if(dp[x])return dp[x];
    58     int mx=0;
    59     for(int i=0;i<pt[x].size();i++){
    60         mx=max(mx,find(pt[x][i]));
    61     }
    62     dp[x]=mx+ptcnt[x];
    63     return dp[x];
    64 }
    65 void solve(){//统计缩完点之后的连通情况 
    66     int i,j,k;
    67     for(i=1;i<=n;i++){
    68         ptcnt[belone[i]]++;
    69         for(j=0;j<e[i].size();j++){
    70             int v=e[i][j];
    71             if(belone[i]!=belone[v])
    72                 pt[belone[i]].push_back(belone[v]);
    73         }
    74     }
    75     int ans=0;
    76     for(i=1;i<=cnt;i++)ans=max(ans,find(i));
    77     printf("%d
    ",ans);
    78     return;
    79 }
    80 int main(){
    81     int T;
    82     scanf("%d",&T);
    83     while(T--){
    84         scanf("%d%d",&n,&m);
    85         clear();
    86         int i,j;
    87         int u,v;
    88         for(i=1;i<=m;i++){
    89             scanf("%d%d",&u,&v);
    90             e[u].push_back(v);
    91         }
    92         for(i=1;i<=n;i++){//缩点 
    93             if(dfn[i]==-1)tarjan(i);
    94         }
    95         solve();
    96     }
    97     return 0;
    98 }
  • 相关阅读:
    关于oracle当中数据类型转换的问题
    CASE WHEN的两种格式
    C#设置默认打印机
    运用Merge Into实现增加或更新数据
    增加或修改的存储过程
    深拷贝与浅拷贝
    sql server两种分页方法
    获取sql执行时间
    inserted触发器,一张表插入数据时,同时向另外一张表插入数据
    List<string[]> 如何去重
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5746531.html
Copyright © 2020-2023  润新知