zoukankan      html  css  js  c++  java
  • BZOJ 1093 [ZJOI2007] 最大半连通子图(强联通缩点+DP)

    题目大意

    题目是图片形式的,就简要说下题意算了

    一个有向图 G=(V, E) 称为半连通的(Semi-Connected),如果满足图中任意两点 u v,存在一条从 u 到 v 的路径或者从 v 到 u 的路径

    给一个有向图(n 个点,m 条边),求出她的最大半连通子图中所包含的点数,以及这样的最大半连通子图有多少个(要求模上一个给定的数 x)

    对于20%的数据, N 18;

    对于60%的数据, N 10000;

    对于100%的数据, N 100000, M 1000000;

    对于100%的数据, X 10^8。

    做法分析

    这种题目在 POJ 做过类似的:POJ 2762 Going from u to v or from v to u? ,它只是询问一个图是否是半连通的,解题报告

    这题其实也差不多的做法,先缩点,重新建图,使其成为一个 DAG,DAG 中每个点有一个点权表示这个点是原图中的几个点缩成的

    新图中的一个最大半连通子图,必然是新图中的一个最长链(点权和最大),知道了这点之后,DP 就行了,类似于树形 DP,先求出从每个点出发,能走的最长链是多长,统计最长的那条就是最大半连通子图的点的数量了,至于怎么求有多少个最大半连通子图,也是一样的 DP 就行,在上一步的 DP 之后,再 DP 一遍,统计每个点出发能走出多少条最长链,最后统计求和即可

    参考代码

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <stack>
     5 #include <vector>
     6 #include <set>
     7 
     8 using namespace std;
     9 
    10 const int N=100005;
    11 
    12 set <pair<int, int> > tub;
    13 stack <int> S;
    14 vector <int> arc[N], adj[N];
    15 int n, m, x, ans1, ans2, T, ind;
    16 int id[N], low[N], dfn[N], cnt[N];
    17 bool vs[N];
    18 
    19 void tarjan(int u) {
    20     dfn[u]=low[u]=T++;
    21     S.push(u), vs[u]=1;
    22     for(int i=0, len=(int)adj[u].size(); i<len; i++) {
    23         int v=adj[u][i];
    24         if(dfn[v]==-1) {
    25             tarjan(v);
    26             if(low[u]>low[v]) low[u]=low[v];
    27         }
    28         else if(vs[v] && low[u]>dfn[v]) low[u]=dfn[v];
    29     }
    30     if(low[u]==dfn[u]) {
    31         while(1) {
    32             int v=S.top();
    33             S.pop(), vs[v]=0;
    34             id[v]=ind, cnt[ind]++;
    35             if(v==u) break;
    36         }
    37         ind++;
    38     }
    39 }
    40 
    41 void DFS1(int u) {
    42     vs[u]=1;
    43     for(int i=0, len=(int)arc[u].size(); i<len; i++) {
    44         int v=arc[u][i];
    45         if(!vs[v]) DFS1(v);
    46         dfn[u]=max(dfn[u], dfn[v]);
    47     }
    48     dfn[u]+=cnt[u];
    49 }
    50 
    51 void DFS2(int u) {
    52     vs[u]=1;
    53     for(int i=0, len=(int)arc[u].size(); i<len; i++) {
    54         int v=arc[u][i];
    55         if(!vs[v]) DFS2(v);
    56         if(dfn[u]==cnt[u]+dfn[v]) id[u]=(id[u]+id[v])%x;
    57     }
    58     if((int)arc[u].size()==0) id[u]=1;
    59     if(dfn[u]==ans1) ans2=(ans2+id[u])%x;
    60 }
    61 
    62 int main() {
    63 //    freopen("in", "r", stdin);
    64     scanf("%d%d%d", &n, &m, &x);
    65     for(int i=1; i<=n; i++) adj[i].clear();
    66     for(int i=0, a, b; i<m; i++) {
    67         scanf("%d%d", &a, &b);
    68         adj[a].push_back(b);
    69     }
    70     fill(dfn, dfn+1+n, -1);
    71     fill(vs, vs+1+n, 0);
    72     T=ind=0;
    73     while(!S.empty()) S.pop();
    74     for(int i=1; i<=n; i++) if(dfn[i]==-1) tarjan(i);
    75     for(int i=0; i<ind; i++) arc[i].clear();
    76     fill(low, low+ind, 0);
    77     tub.clear();
    78     for(int i=1; i<=n; i++)
    79         for(int j=0, len=(int)adj[i].size(); j<len; j++) {
    80             int v=id[adj[i][j]], u=id[i];
    81             if(u==v) continue;
    82             if(tub.find(make_pair(u, v))!=tub.end()) continue;
    83             low[v]++, arc[u].push_back(v);
    84             tub.insert(make_pair(u, v));
    85         }
    86     fill(vs, vs+ind, 0);
    87     fill(dfn, dfn+ind, 0);
    88     ans1=0, ans2=0;
    89     for(int i=0; i<ind; i++) if(low[i]==0) {
    90         DFS1(i);
    91         ans1=max(ans1, dfn[i]);
    92     }
    93     fill(vs, vs+ind, 0);
    94     fill(id, id+ind, 0);
    95     for(int i=0; i<ind; i++) if(low[i]==0) DFS2(i);
    96     printf("%d
    %d
    ", ans1, ans2);
    97     return 0;
    98 }
    BZOJ 1093

    题目链接 & AC 通道

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

  • 相关阅读:
    【iOS学习笔记】iOS启动顺序
    【iOS学习笔记】iOS算法(四)之冒泡排序
    【iOS学习笔记】iOS算法(五)之折半查找
    【iOS学习笔记】iOS算法(三)之插入排序
    【iOS学习笔记】iOS算法(二)之选择排序
    【iOS学习笔记】iOS算法(一)快速排序算法
    【iOS学习笔记】iOS ⾃自定义cell的步骤
    【iOS学习笔记】IOS开发中设置applicationIconBadgeNumber和消息推送
    【iOS学习笔记】iOS 9:改用更安全的HTTPS
    2015/10/6 iOS 笔记 细节 应用中常见文件
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3267311.html
Copyright © 2011-2022 走看看