zoukankan      html  css  js  c++  java
  • [BZOJ4304]/[JZOJ3486]道路改建

    题目大意:
      给你一个有向图,你可以把其中某一条单向边改成双向边,使得图中最大的SCC最大。
      问SCC最大能是多少,有哪些方案?

    思路:
      对原图缩点后就变成了一个DAG。
      我们在DAG上DP,记录一下从点i出发能到达的点集out[i],以及能到达i的点的集合in[i]。
      最后枚举每一条边(u->v),将它改为双向边就相当于将所有u,v之间的点都连通起来,也就是求out[u]和in[v]的交。
      最后我们看一下哪个交最大,以及这么大的有哪些边即可。
      注意要用bitset优化,不然只有60分。

    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<bitset>
    #include<vector>
    inline int getint() {
        register char ch;
        while(!isdigit(ch=getchar()));
        register int x=ch^'0';
        while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
        return x; 
    }
    const int N=2001,M=4000000;
    struct Edge {
        int u,v;
    };
    Edge edge[M];
    std::vector<int> e[N],e2[N];
    inline void add_edge(const int &u,const int &v) {
        e[u].push_back(v);
    }
    int ind[N],outd[N];
    std::bitset<N> in[N],out[N];
    int dfn[N],low[N],scc[N],cnt,id;
    std::stack<int> s;
    bool ins[N];
    void tarjan(const int &x) {
        dfn[x]=low[x]=++cnt;
        s.push(x);
        ins[x]=true;
        for(register unsigned i=0;i<e[x].size();i++) {
            const int &y=e[x][i];
            if(!dfn[y]) {
                tarjan(y);
                low[x]=std::min(low[x],low[y]);
            } else if(ins[y]) {
                low[x]=std::min(low[x],dfn[y]);
            }
        }
        if(dfn[x]==low[x]) {
            id++;
            int y=0;
            while(y!=x) {
                y=s.top();
                s.pop();
                ins[y]=false;
                scc[y]=id;
                in[id].set(y);
                out[id].set(y);
            }
        }
    }
    inline void kahn(const std::vector<int> e[],int deg[],std::bitset<N> set[]) {
        static std::queue<int> q;
        for(register int i=1;i<=id;i++) {
            if(!deg[i]) {
                q.push(i);
            }
        }
        while(!q.empty()) {
            const int x=q.front();
            q.pop();
            for(register unsigned i=0;i<e[x].size();i++) {
                const int &y=e[x][i];
                set[y]|=set[x];
                if(!--deg[y]) {
                    q.push(y);
                }
            }
        }
    }
    int main() {
        int n=getint(),m=getint();
        for(register int i=0;i<m;i++) {
            edge[i]=(Edge){getint(),getint()};
            add_edge(edge[i].u,edge[i].v);
        }
        for(register int i=1;i<=n;i++) {
            if(!dfn[i]) {
                tarjan(i);
            }
            e[i].clear();
        }
        for(register int i=0;i<m;i++) {
            const int &u=scc[edge[i].u],&v=scc[edge[i].v];
            if(u==v) continue;
            e[u].push_back(v);
            e2[v].push_back(u);
            outd[u]++,ind[v]++;
        }
        kahn(e,ind,in);
        kahn(e2,outd,out);
        unsigned ans=0;
        static std::vector<int> vec;
        for(register int i=0;i<m;i++) {
            const int &u=scc[edge[i].u],&v=scc[edge[i].v];
            if((out[u]&in[v]).count()>ans) {
                ans=(out[u]&in[v]).count();
                vec.clear();
                vec.push_back(i+1);
            } else if((out[u]&in[v]).count()==ans) {
                vec.push_back(i+1);
            }
        }
        printf("%u
    %llu
    ",ans,vec.size());
        for(register unsigned i=0;i<vec.size();i++) {
            printf("%d ",vec[i]);
        }
        return 0;
    }
  • 相关阅读:
    mysq 日期相减
    说说时间观与时间管理——北漂18年(71)
    ionic之切换开关
    ionic之单选框
    SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE locks在RR模式下可以看到最新的记录
    14.5.2.3 Consistent Nonlocking Reads 一致性非锁定读
    14.5.2.2 autocommit, Commit, and Rollback
    14.5.2 事务隔离级别
    对于唯一索引使用唯一条件搜索, InnoDB 只锁定找到的index record,不是它之前的区间
    mysql explain 解释
  • 原文地址:https://www.cnblogs.com/skylee03/p/7765548.html
Copyright © 2011-2022 走看看