hdu 4635 Strongly connected (tarjan)

hdu 4635 Strongly connected (tarjan)

大家好,又见面了,我是全栈君。

题意:给一个n个顶点m条弧的简单有向图(无环无重边),求最多能够加入多少条弧使得加入后的有向图仍为简单有向图且不是一个强连通图。假设给的简单有向图本来就是强连通图,那么输出-1.


分析:

1.用tarjan算法求出强连通分量的个数,假设个数为1,那么输出-1,结束,否则运行2

2.如果将一些强连通分量合并为有n1个顶点简单全然图1,而将剩下的强连通分量合并为n2个顶点的简单全然图2,跨这两个简单全然图的弧的方向仅仅能是单向的,如果m1为全然图1内部的弧的数量,m2为为全然图2内部的弧的数量。m3为跨这两个简单全然图的弧的数量,那么

 ans=n1*(n1-1)-m1+n2*(n2-1)-m2+n1*n2-m3  —————————————————-1式

 n1+n2=n                                                            —————————————————-2式

 m1+m2+m3=m                                                 —————————————————-3式

 n*n=(n1+n2)(n1+n2)=n1*n1+n2*n2+2*n1*n2 —————————————————–4式

所以

ans=n*n-m-n-n1*n2=n*n-m-n-n1*(n-n1)

ans要最大,所以n1*(n-n1)要最小。同一时候要跨图1。图2的弧要单向,

所以在跨图1,图2的弧要单向的情况下。n1尽量小。


代码:
#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX 100005#define INF 1<<30using namespace std;typedef struct ArcNode{    int adjvex;//该弧所指向的顶点的位置    struct ArcNode * nextarc;//指向下一条弧的指针} ArcNode;typedef struct VNode{    int vertex;    //int In_deg,Out_deg;    int belong;    ArcNode * firstarc;} VNode;VNode V[MAX];int DFN[MAX],Stack[MAX],low[MAX];int top,index,bcnt;bool instack[MAX];long long n,m;int Min;int cnt;int k;int edge[MAX][2];void init(){    int a,b;    ArcNode * p;    for(int i=1; i<=n; i++)    {        V[i].vertex=i;        //V[i].In_deg=V[i].Out_deg=0;        V[i].firstarc =NULL;    }    for(int i=0; i<m; i++)    {        scanf("%d%d",&a,&b);       // V[a].Out_deg++;       // V[b].In_deg++;       edge[i][0]=a;       edge[i][1]=b;        p=(ArcNode*)malloc(sizeof(ArcNode));        p->adjvex =b;        p->nextarc =V[a].firstarc ;        V[a].firstarc =p;    }}void DFS_tarjan(int i){    int j;    ArcNode * p;    DFN[i]=low[i]=++index;    Stack[++top]=i;    instack[i]=true;    p=V[i].firstarc ;    while(p!=NULL)    {        j=p->adjvex;        if(!DFN[j])        {            DFS_tarjan(j);            if(low[j]<low[i])//Low(u)为u的子树可以追溯到的最早的栈中节点的次序号                low[i]=low[j];        }        else if(instack[j]&&DFN[j]<low[i])//Low(u)为u可以追溯到的最早的栈中节点的次序号            low[i]=DFN[j];        p=p->nextarc;//    }    if(DFN[i]==low[i])    {        bcnt++;        cnt=0;        int INDEG=0;        int OUTDEG=0;        do        {            j=Stack[top--];//出栈,j是为该强连通分量中一个顶点            instack[j]=false;            //INDEG+=V[j].In_deg;            //OUTDEG+=V[j].Out_deg;            V[j].belong=bcnt;            cnt++;        }        while(i!=j);        for(int kkk=0;kkk<m;kkk++)        {            if(V[edge[kkk][0]].belong==bcnt&&V[edge[kkk][1]].belong!=bcnt)            {                OUTDEG++;            }            if(V[edge[kkk][0]].belong!=bcnt&&V[edge[kkk][1]].belong==bcnt)                INDEG++;        }        if(Min>cnt&&(INDEG==0||OUTDEG==0))        {            Min=cnt;        }    }}void FREE(){    ArcNode * p;    ArcNode * q;    for(int i=1; i<=n; i++)    {        p=V[i].firstarc;        while(p!=NULL)        {            q=p;            p=p->nextarc;            free(q);        }    }}void solve(){    int i;    top=index=bcnt=0;    memset(DFN,0,sizeof(DFN));    memset(instack,false,sizeof(instack));    for(i=1; i<=n; i++)    {        if(!DFN[i])            DFS_tarjan(i);    }    //printf("%d\n",bcnt);    FREE();    if(bcnt==1)    {        printf("Case %d: -1\n",k);        return;    }    long long ans=n*n-n-m-(Min*(n-Min));    //printf("%d\n",Min);    printf("Case %d: %lld\n",k,ans);}int main(){    int t;    scanf("%d",&t);    for(k=1; k<=t; k++)    {        scanf("%lld%lld",&n,&m);        Min=INF;        init();        solve();    }    return 0;}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115821.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • navicat for mysql 15 永久激活码_通用破解码

    navicat for mysql 15 永久激活码_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月17日
    844
  • Python绘图Turtle库详解[通俗易懂]

    Python绘图Turtle库详解[通俗易懂]Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行的路径上绘制了图形。turtle绘图的基础知识:1.画布(canvas)画布就是turtle为我们展开用于绘图区域,我们可以设置它的大小和初始位置。…

    2022年6月9日
    58
  • plc-300c语言编程,PLC初学者必备:7个PLC经典编程[通俗易懂]

    plc-300c语言编程,PLC初学者必备:7个PLC经典编程[通俗易懂]1、自锁(启保停)自锁需要并联一个线圈输出的常开触点,当启动后,并联的常开触点起到维持输出继续闭合的作用,就是自锁。我们最常用的启保停程序就是自锁。2、连锁和互锁(正反转)连锁就是用两个或多个信号控制一个输出,其实就是触点串联程序。互锁其实是连锁的扩展,利用一个程序行的输出信号作为其他程序行的连锁触点,相互之间进行运行控制,就是互锁。当两个或多个输出之间存在不能同时运行的情况时,就需要用到互锁,比…

    2022年9月6日
    5
  • Selenium系列4-元素定位

    Selenium系列4-元素定位

    2021年11月30日
    51
  • mapreduce编程初探[通俗易懂]

    mapreduce编程初探[通俗易懂]1.map和reduce1.1mapReduce处理逻辑在本系列文章的第一篇中,曾对MapReduce原理做过简单的描述,在这里再重述一遍。 首先我们有两个文件word1.txt和word2.txt 其中word1.txt的内容如下:aaaabbbbccccddddaaaaword2.txt的内容如下:aaaaccccddddeeeeaaaa这…

    2022年6月29日
    25
  • python海龟绘图画圆_Python启蒙之海龟作图「建议收藏」

    python海龟绘图画圆_Python启蒙之海龟作图「建议收藏」今天我要向大家介绍一下如何使用Python进行绘图,学会了基本绘图后,你就可以使用电脑绘制出很多漂亮的图形了,先给大家展示几幅使用Python绘图完成的精美图案吧。这副图形电脑是如何绘制出来的呢?试想一下,如果现在给你一张纸和一支笔,你如何做出这幅图形。你可以从中心点开始,然后一条条线开始绘制,直到完成最边缘的线条。电脑作图的方式就是充分模拟了你手工绘画的流程,通过程序控制了手工的作图。那既…

    2022年6月28日
    118

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号