hdu4635Strongly connected 【求最多加多少边仍不是强连通分量】

这道题其实做完之后发现几乎就是模板题,然而之前有个地方想了一周一直拧不过来,题目是最多加多少条边仍然不是强连通图,也就可以理解为再多加一条边就无论如何都是强连通图,等价于最多去掉几条边使之仍未强连通图,当此时再多去一条边的时候,等价于最少去掉几条变使原图不强连通,好了终于绕完了,都给我自己绕蒙了,那么我们是最少去掉多少条边使原图不强联通,我们先把它变成一个完全图,然后再减去题目中给的边

ans=n*(n-1)-m-x,至于这个x是多少呢,就是我最少要去掉的边数,因为x=(n-a)*a,n是一定的a和(n-a)差越大,二者乘积就越小,ans就越大,所以我们要做的就是把那些缩点分成两个集合,一个集合里是所有缩点中点的个数最小的集合,其他的缩点放在另一个集合里,并且那个单独在一个集合的缩点,一定要满足入度或出度为0,因为只有这样才能保证这个边是只有一个方向的,也就是没有环,不是强连通的

还有就是判-1,只用团的个数,最终结果可能等于0!

#include <iostream>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;
const int maxn=200005;
vector <int>G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int>S;
void dfs(int u)
{
    pre[u]=lowlink[u]=++dfs_clock;
    S.push(u);
    for(int i=0; i<G[u].size(); i++)
    {
        int v=G[u][i];
        if(!pre[v])
        {
            dfs(v);
            lowlink[u]=min(lowlink[u],lowlink[v]);

        }
        else if(!sccno[v])
        {
            lowlink[u]=min(lowlink[u],pre[v]);
        }
    }
    if(lowlink[u]==pre[u])
    {
        scc_cnt++;
        for(;;)
        {
            int x=S.top();
            S.pop();
            sccno[x]=scc_cnt;
            if(x==u)
                break;
        }
    }
}
void find_scc(int n)
{
    dfs_clock=scc_cnt=0;
    memset(sccno,0,sizeof(sccno));
    memset(pre,0,sizeof(pre));
    for(int i=0; i<n; i++)if(!pre[i])dfs(i);
}

int in0[maxn],out0[maxn];
int main()
{
    int T,n,m,cas=1;
    int num[maxn];
    scanf("%d",&T);
    while(T--)
    {
        memset(in0,0,sizeof(in0));
        memset(out0,0,sizeof(out0));
        memset(num,0,sizeof(num));
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
            G[i].clear();
        for(int i=0; i<m; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            u--;
            v--;
            G[u].push_back(v);
        }
        find_scc(n);
        for(int i=1; i<=scc_cnt; i++)
            in0[i]=out0[i]=1;
        for(int u=0; u<n; u++)
        {
            for(int i=0; i<G[u].size(); i++)
            {
                int v=G[u][i];
                if(sccno[u]!=sccno[v])
                    in0[sccno[v]]=out0[sccno[u]]=0;
            }
            num[sccno[u]]++;
        }
        int maxnum=maxn;
        for(int  i=1; i<=scc_cnt; i++)
        {
            if(in0[i]==1||out0[i]==1)
            {
                if(num[i]<maxnum)
                    maxnum=num[i];
            }
        }
        //cout<<maxnum<<endl;
        long long ans=n*(n-1)-m-(n-maxnum)*maxnum;
        if(scc_cnt!=1) printf("Case %d: %lld\n",cas++,ans);
        else printf("Case %d: -1\n",cas++);

    }
    return 0;
}

时间: 2024-10-26 11:51:15

hdu4635Strongly connected 【求最多加多少边仍不是强连通分量】的相关文章

HDU 4635 —— Strongly connected——————【 强连通、最多加多少边仍不强连通】

Strongly connected Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4635 Description Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the edges you can

POJ 1236--Network of Schools【scc缩点构图 &amp;&amp; 求scc入度为0的个数 &amp;&amp; 求最少加几条边使图变成强联通】

Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13325   Accepted: 5328 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a li

poj 3384 Feng Shui 半平面交的应用 求最多覆盖凸多边形的面积的两个圆 的圆心坐标

题目来源: http://poj.org/problem?id=3384 分析: 用半平面交将多边形的每条边一起向"内"推进R,得到新的多边形(半平面交),然后求多边形的最远两点. 代码如下: const double EPS = 1e-10; const int Max_N = 105 ; struct Point{ double x,y; Point(){} Point(double x, double y):x(x),y(y){} Point operator - (Point

Board Wrapping(计算几何求凸包加向量的旋转)

UVA - 10652 Board Wrapping Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit]   [Go Back]   [Status] Description Problem B Board Wrapping Input: standard input Output: standard output Time Limit: 2 seconds The small sa

HDU 4635 Strongly connected (有向图的强连通分量)

Strongly connected Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the edges you can add that the grap

图论算法(6) --- Tarjan算法求强连通分量

注:此算法以有向图作为输入,并按照所在的强连通分量给出其顶点集的一个划分.graph中的每个节点只在一个强连通分量里出现,即使是单点. 任选一点开始进行深度优先搜索(若dfs结束后仍有未访问的节点,则再从中任选一点再从进行).搜索过程中已访问的节点不再访问.搜索树的若干子树构成了图的强连通分量. 节点按照被访问的顺序存入栈中.从搜索树的子树返回至一个节点时,检查该节点是否是某一连通分量的根节点,并将其从栈中删除.如果某节点是强连通分量的根,则在它之前出栈且还不属于其他强连通分量的节点构成了该节点

POJ1236 (强连通分量缩点求入度为0和出度为0的分量个数)

Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13804   Accepted: 5507 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a li

HDU 4635 Strongly connected(强连通分量缩点+数学思想)

题意:给出一个图,如果这个图一开始就不是强连通图,求出最多加多少条边使这个图还能保持非强连通图的性质. 思路:不难想到缩点转化为完全图,然后找把它变成非强连通图需要去掉多少条边,但是应该怎么处理呢……有人给出这样的答案,找到分量中点数最少的块,把它的所有入边都去掉……好像是对的,但是万一这个块本来就有一个入度怎么办?这个边是不可以删的啊.所以我觉得这种办法是有点的问题的,所以最靠谱的方法还是斌哥他们给出的方法,最后的时候把点分成两个集合x和y,x和y本身都是完全图块,然后让x中的每一个点都指向y

HDU 4635 Strongly connected(强连通分量,变形)

题意:给出一个有向图(不一定连通),问最多可添加多少条边而该图仍然没有强连通. 思路: 强连通分量必须先求出,每个强连通分量包含有几个点也需要知道,每个点只会属于1个强连通分量. 在使图不强连通的前提下,要添加尽可能多的边.边至多有n*(n-1)条,而已经给了m条,那么所能添加的边数不可能超过k=n*(n-1)-m. 这k条边还有部分不能添加,一添加立刻就强连通.一个强连通图最少只需要n条边,根据强连通的特性,缩点之后必定是不会有环的存在的,那么只要继续保持没有环的存在即可.我们只要让其中1个强