zoukankan      html  css  js  c++  java
  • hdu4635 有向点双

    题:http://acm.hdu.edu.cn/showproblem.php?pid=4635

    题意:给n个点m条边的有向图,问最多还能添加多少条边,让此图还不能形成强连通图;

    分析:tarjan缩点后,我们知道要是点双的个数是1那么肯定不符合条件,就直接输出-1;

       那么剩下的情况就是,我们挑出一个点双,让剩余的点双全连通起来,当前点的点双也全连通起来,就剩下俩个点双,俩个点双之间也要尽可能连边;

       我们假设当前点双为 i ,剩下的点双 为 j (已经全连通过了),那么要是一开始 j 中的俩个点双分为对 i 有入边和出边,那么 i 和 j 就肯定能连通,就不满足条件了,所以我们要挑那些要么入度为0要么出度为0要么度数为0的点点双来考虑;

       对于每一个点双,答案贡献有三部分:1、当前点双 i 还能添加多少条边达到全连通;

                        2、剩下点双 j 还能添加多少条边达到全连通;

                        3、i 和 j 之间还能添加多少条边让i 和 j 不连通(i 和 j 之间的边要么全是出边要么全是入边)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    const int M=1e5+5;
    vector<int>g[M];
    int dfn[M],low[M],sta[M],cmp[M],in[M],out[M],n,m,top,tot,cnt;
    bool vis[M];
    ll sum[M],du[M],line[M];
    void tarjan(int u){
        dfn[u]=low[u]=++cnt;
        sta[++top]=u;
        vis[u]=true;
        for(int i=0;i<g[u].size();i++){
            int v=g[u][i];
            if(!dfn[v]){
                tarjan(v),low[u]=min(low[u],low[v]);
            }
            else if(vis[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u]){
            cmp[u]=++tot;
            vis[u]=false;
            int len=top;
            while(sta[top]!=u){
                cmp[sta[top]]=tot;
                vis[sta[top--]]=false;
            }
            top--;
            sum[tot]=len-top;
        }
    }
    void init(){
        tot=top=cnt=0;
        for(int i=0;i<=n;i++)
            g[i].clear(),cmp[i]=0,low[i]=0,dfn[i]=0,out[i]=0,in[i]=0,line[i]=0,du[i]=0,sum[i]=0;
    }
    int main(){
        int t;
        scanf("%d",&t);
        for(int p=1;p<=t;p++){
            scanf("%d%d",&n,&m);
            init();
            for(int u,v,i=1;i<=m;i++){
                scanf("%d%d",&u,&v);
                g[u].pb(v);
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i])
                    tarjan(i);
            printf("Case %d: ",p);
            if(tot==1){
                puts("-1");
                continue;
            }
            ll ans=0;
            for(int i=1;i<=n;i++)
                for(int j=0;j<g[i].size();j++){
                    int v=g[i][j];
                    if(cmp[i]!=cmp[v]){
                        out[cmp[i]]++;
                        in[cmp[v]]++;
                        du[cmp[i]]++;
                        du[cmp[v]]++;
                    }
                    else line[cmp[i]]++;
                }
            for(int i=1;i<=tot;i++){
                ll nownum=1ll*(n-sum[i]);
                ll sum1=nownum*(nownum-1);///外面的连通块的总边数; 
                ll sum2=1ll*(m-line[i]-du[i]);///外面的连通块已经连的边数;
                ll sum3=sum[i]*nownum-du[i];///当前点可以再和外面连多少边;
                ll sum4=sum[i]*(sum[i]-1)-line[i];///当前连通块里还可以连的边 
            //    cout<<sum1-sum2<<"@@"<<sum3<<"@@"<<sum4<<endl;
                if(!du[i]||!in[i]||!out[i]){
                    ans=max(ans,(sum1-sum2)+sum3+sum4);
                //    ans=max(ans,sum1-(m-line[i]-du[i])+sum[i]*nownum-du[i]);
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Vuforia7+Unity2017.3.f3实践练习
    pureMVC+unity
    sql语法小结
    ScreenToViewportPoint,WorldToViewportPoint,ViewportToWorldPoint的运用,实现一个简单的对三维中物体的拖拽移动效果
    Unity游戏开发学习之路——数据持久化
    Unity游戏开发之路上的那些坑——NullReferenceException
    ffmpeg-音频视频处理
    微信开发之(五)接收语音识别结果
    微信开发之(五)获取media_id的值
    微信开发之(五)微信获取自定义菜单
  • 原文地址:https://www.cnblogs.com/starve/p/12427730.html
Copyright © 2011-2022 走看看