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<<30
using 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;
}
时间: 2024-10-12 14:36:28

hdu 4635 Strongly connected (tarjan)的相关文章

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

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

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

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

[tarjan] hdu 4635 Strongly connected

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4635 Strongly connected Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1568    Accepted Submission(s): 654 Problem Description Give a simple dir

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

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

HDU 4635 Strongly connected(强连通)经典

Strongly connected Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1828    Accepted Submission(s): 752 Problem Description Give a simple directed graph with N nodes and M edges. Please tell me

Hdu 4635 Strongly connected

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4635 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 const int maxn = 100005; 9 const int INF

HDU 4635 Strongly connected 强连通分量

参考:http://www.cnblogs.com/jackge/p/3231767.html 讲的很好 感悟:最好的情况肯定是完全图,但是不允许,所以一定是有些符合u->v,但是v不能到u, 在保证这样的情况,最大化边数,最终会形成两个图,然后应用不等式 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath>

hdu 1269 迷宫城堡 (tarjan算法学习)

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7056    Accepted Submission(s): 3137 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A