• Uva 11324 The Largest Clique【强连通 DAG动规 spfa】


    白书上的例题

    做一遍tarjan后,缩点,每一个scc节点的权为它的结点数,做一次DAG上的动规,求出路径上的最大点权和,就可以了

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<stack>
      6 #include<vector>
      7 using namespace std;
      8 
      9 const int maxn = 5005;
     10 int n,m;
     11 int first[maxn];
     12 int sc[maxn],scn[maxn],low[maxn],pre[maxn];
     13 int scnt,ecnt,dfs_clock;
     14 int dp[maxn];
     15 
     16 int first1[maxn];
     17 int ecnt1;
     18 
     19 struct Edge{
     20     int v,next;
     21 }e[maxn*10];
     22 
     23 Edge e1[maxn*10];
     24 
     25 stack<int> S;
     26 
     27 void init(){
     28     ecnt = ecnt1 = 0;
     29     memset(first,-1,sizeof(first));
     30     memset(first1,-1,sizeof(first1));
     31     memset(dp,0,sizeof(dp));
     32 }
     33 
     34 void addedges(int u,int v){
     35     e[ecnt].v = v;
     36     e[ecnt].next = first[u];
     37     first[u] = ecnt++;
     38 }
     39 
     40 void addedges1(int u,int v){
     41     e1[ecnt1].v = v;
     42     e1[ecnt1].next = first1[u];
     43     first1[u] = ecnt1++;
     44 }
     45 
     46 void dfs(int u){
     47     low[u] = pre[u] = ++dfs_clock;
     48     S.push(u);
     49     for(int i = first[u];~i;i = e[i].next){
     50         int v = e[i].v;
     51         if(!pre[v]){
     52             dfs(v);
     53             low[u] = min(low[u],low[v]);
     54         }
     55         else if(!sc[v]) low[u] = min(low[u],pre[v]);
     56     }
     57     if(pre[u] == low[u]){
     58         scnt++;
     59         for(;;){
     60             int x = S.top();S.pop();
     61             sc[x] = scnt;
     62             scn[scnt]++;
     63             if(x == u) break;
     64         }
     65     }
     66 }
     67 
     68 void find_scc(){
     69     while(!S.empty()) S.pop();
     70     scnt = dfs_clock = 0;
     71     memset(low,0,sizeof(low));memset(pre,0,sizeof(pre));
     72     memset(sc,0,sizeof(sc));memset(scn,0,sizeof(scn));
     73     
     74     for(int i = 1;i <= n;i++) if(!pre[i]) dfs(i);
     75 }
     76 
     77 int solve(int p){
     78     if(dp[p]) return dp[p];
     79     for(int i = first1[p];~i;i = e1[i].next){
     80         int v = e1[i].v;
     81         dp[p] = max(dp[p],solve(v));
     82     }
     83     return dp[p] = dp[p] + scn[p];
     84 }
     85 
     86 
     87 int main(){
     88     int T;
     89     scanf("%d",&T);
     90     while(T--){
     91         init();
     92         scanf("%d %d",&n,&m);
     93         for(int i = 0;i < m;i++ ){
     94             int u,v;
     95             scanf("%d %d",&u,&v);
     96             addedges(u,v);
     97         }
     98         find_scc();
     99         
    100         for(int u = 1;u <= n;u++){
    101             for(int i = first[u];~i;i = e[i].next){
    102                 int v = e[i].v;
    103                 if(sc[u] != sc[v]) addedges1(sc[u],sc[v]);
    104             }
    105         }
    106         
    107 
    108         int ans = 0;
    109         for(int i = 1;i <= scnt;i++) ans = max(ans,solve(i));
    110         printf("%d
    ",ans);
    111     }
    112     return 0;
    113 }
    View Code


    还有另一种做法是,建立一个超级源点,与入度为0的scc节点连接,做一次spfa,求出路径上的最大点权和

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<stack>
      6 #include<vector>
      7 #include<queue>
      8 using namespace std;
      9 
     10 const int maxn = 5005;
     11 const int INF = 1000000005;
     12 int n,m;
     13 int first[maxn];
     14 int sc[maxn],scn[maxn],low[maxn],pre[maxn];
     15 int scnt,ecnt,dfs_clock;
     16 int dp[maxn];
     17 
     18 int du[maxn];
     19 int dis[maxn];
     20 int inq[maxn];
     21 
     22 int first1[maxn];
     23 int ecnt1;
     24 
     25 struct Edge{
     26     int v,next;
     27 }e[maxn*10];
     28 
     29 Edge e1[maxn*10];
     30 
     31 stack<int> S;
     32 vector<int> g[maxn];
     33 int val[maxn];
     34 
     35 void init(){
     36     ecnt = ecnt1 = 0;
     37     memset(first,-1,sizeof(first));
     38     memset(val,0,sizeof(val));
     39     memset(du,0,sizeof(du));       
     40 }
     41 
     42 void addedges(int u,int v){
     43     e[ecnt].v = v;
     44     e[ecnt].next = first[u];
     45     first[u] = ecnt++;
     46 }
     47 
     48 void dfs(int u){
     49     low[u] = pre[u] = ++dfs_clock;
     50     S.push(u);
     51     for(int i = first[u];~i;i = e[i].next){
     52         int v = e[i].v;
     53         if(!pre[v]){
     54             dfs(v);
     55             low[u] = min(low[u],low[v]);
     56         }
     57         else if(!sc[v]) low[u] = min(low[u],pre[v]);
     58     }
     59     if(pre[u] == low[u]){
     60         scnt++;
     61         for(;;){
     62             int x = S.top();S.pop();
     63             sc[x] = scnt;
     64             val[scnt]++;
     65             if(x == u) break;
     66         }
     67     }
     68 }
     69 
     70 void find_scc(){
     71     while(!S.empty()) S.pop();
     72     scnt = dfs_clock = 0;
     73     memset(low,0,sizeof(low));memset(pre,0,sizeof(pre));
     74     memset(sc,0,sizeof(sc));memset(scn,0,sizeof(scn));
     75     
     76     for(int i = 1;i <= n;i++) if(!pre[i]) dfs(i);
     77 }
     78 
     79 
     80 int spfa(){  
     81     memset(inq, 0, sizeof(inq));  
     82     queue<int>q;  
     83     g[0].clear();  
     84     q.push(0);  
     85     dis[0] = 0; val[0] = 0;  
     86     for(int i = 1; i <= scnt; i++){if(du[i] == 0)g[0].push_back(i); dis[i] = -INF;}  
     87     int ans = 0;  
     88     while(!q.empty()){  
     89         int u = q.front(); q.pop(); inq[u] = 0;  
     90         for(int i = 0; i < g[u].size(); i++){  
     91             int v = g[u][i];  
     92             if(dis[v] < dis[u] + val[v]){  
     93                 dis[v] = dis[u] + val[v];  
     94                 ans = max(ans, dis[v]);  
     95                 if(inq[v] == 0)inq[v] = 1, q.push(v);  
     96             }  
     97         }  
     98     }  
     99     return ans;  
    100 }  
    101 
    102 int main(){
    103     int T;
    104     scanf("%d",&T);
    105     while(T--){
    106         init();
    107         scanf("%d %d",&n,&m);
    108         for(int i = 0;i < m;i++ ){
    109             int u,v;
    110             scanf("%d %d",&u,&v);
    111             addedges(u,v);
    112         }
    113         find_scc();
    114         for(int i = 1;i <= scnt;i++) g[i].clear();
    115     
    116         for(int u = 1;u <= n;u++){
    117             for(int i = first[u];~i;i = e[i].next){
    118                 int v = e[i].v;
    119                 if(sc[u] != sc[v]) g[sc[u]].push_back(sc[v]),du[sc[v]]++;
    120             }
    121         }
    122         printf("%d
    ",spfa());
    123     }
    124     return 0;
    125 }
    View Code
  • 相关阅读:
    让最新官方编译的 ffmpeg 在 XP 上 跑起来
    A young man asks a homeless man to borrow his bucket, what happens next will burst you into tears
    ada 图形编辑器
    ffmpeg-20160718-git-bin.7z
    ffmpeg-20160714-git-bin.7z
    opencv-3.x.0-x86-mingw32-staticlib-gcc5.3.0-20160712.7z
    全能直播王PC版-0707-full_codecs
    ffmpeg-20160701-git-bin.7z
    ffmpeg-20160629-git-bin.7z
    bugku | 你从哪里来
  • 原文地址:https://www.cnblogs.com/wuyuewoniu/p/4700227.html
Copyright © 2020-2023  润新知