zoukankan      html  css  js  c++  java
  • bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp

    一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
    两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,
    则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图
    中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
    ,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

    解法:把scc缩点,同一个连通分量里肯定互相可达,然后变成了dag,只需要跑一个dag上dp找最长路即可,然后需要记录一下最长路方案数,需要注意的确定点之后边就确定了,所以scc缩点时需要判一下重边

    /**************************************************************
        Problem: 1093
        User: walfy
        Language: C++
        Result: Accepted
        Time:4788 ms
        Memory:49420 kb
    ****************************************************************/
     
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
     
    using namespace std;
     
    const double g=10.0,eps=1e-11;
    const int N=100000+10,maxn=1000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
     
    int n,m,X;
    stack<int>s;
    vector<int>v[N],vv[N],ans[N];
    int dfn[N],low[N];
    int ins[N],inans[N];
    int num,ind;
    int a[maxn],b[maxn];
    void tarjan(int u)
    {
        ins[u]=2;
        low[u]=dfn[u]=++ind;
        s.push(u);
        for(int i=0;i<v[u].size();i++)
        {
            int t=v[u][i];
            if(dfn[t]==0)
            {
                tarjan(t);
                low[u]=min(low[u],low[t]);
            }
            else if(ins[t]==2)low[u]=min(low[u],dfn[t]);
        }
        if(low[u]==dfn[u])
        {
            ++num;
            while(!s.empty()){
                int k=s.top();
                s.pop();
                ins[k]=1;
                ans[num].push_back(k);
                inans[k]=num;
                if(k==u)break;
            }
        }
    }
    map<pii,int>ma;
    void scc()
    {
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
        for(int i=0;i<m;i++)
        {
            int x=inans[a[i]],y=inans[b[i]];
            if(x!=y&&!ma[mp(x,y)])vv[x].pb(y),ma[mp(x,y)]=1;
        }
    }
    pii dp[N];
    pii DP(int u)
    {
        if(dp[u].fi!=-1)return dp[u];
        dp[u].fi=ans[u].size(),dp[u].se=1;
        for(int i=0;i<vv[u].size();i++)
        {
            int x=vv[u][i];pii te=DP(x);
            if(dp[u].fi<te.fi+ans[u].size())
            {
                dp[u]=te,dp[u].fi=te.fi+ans[u].size();
    //            printf("%d %d %d %d
    ",u,x,dp[u].fi,dp[u].se);
            }
            else if(dp[u].fi==te.fi+ans[u].size())
            {
                dp[u].se=(dp[u].se+te.se)%X;
    //            printf("%d %d %d +++%d
    ",u,x,dp[u].se,te.se);
            }
        }
        return dp[u];
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&X);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a[i],&b[i]);
            v[a[i]].pb(b[i]);
        }
        scc();
        memset(dp,-1,sizeof dp);
        for(int i=1;i<=n;i++)
            DP(i);
        int ma=0;
        for(int i=1;i<=num;i++)ma=max(ma,dp[i].fi);//,printf("%d %d
    ",dp[i].fi,dp[i].se);
        int ans=0;
        for(int i=1;i<=num;i++)if(dp[i].fi==ma)ans=(ans+dp[i].se)%X;
        printf("%d
    %d
    ",ma,ans);
        return 0;
    }
    /***********************
     
    ***********************/
    
    View Code
  • 相关阅读:
    【转】你可能不知道的Shell
    【转】28个Unix/Linux的命令行神器
    ubuntu创建桌面快捷方式
    linux解压zip乱码解决方案
    全能系统监控工具dstat
    【转】linux sar命令详解
    等级保护测评策略建议整改措施
    oracle dataguard详解和环境搭建
    Oracle RMAN备份和异机恢复
    Oracle异机恢复处理
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9000610.html
Copyright © 2011-2022 走看看