hdu 2767 强连通缩点处理加边问题

#include <cstring>
#include <cstdlib>
#include <cstdio>
缩点的好处就是可以将乱七八糟的有向图 转化为无环的有向图#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>
using namespace std;
#define MAXN 200010
#define clr(x,k) memset((x),(k),sizeof(x))
struct node
{
    int st,to,next;
}
edge[MAXN];
int n,m,ct,id;
int head[MAXN],low[MAXN],dfn[MAXN],belong[MAXN],in[MAXN],to[MAXN];
//DFN[i]表示 遍历到 i 点时是第几次dfs
//Low[u] 表示 以u点为父节点的 子树 能连接到 [栈中] 最上端的点 的DFN值
bool instack[MAXN];
stack<int>q;
void add_e(int i,int u,int v)
{
    edge[i].st=u;
    edge[i].to=v;
    edge[i].next=head[u];
    head[u]=i;
}
void tarjan(int i)
{
    int j;
    dfn[i]=low[i]=++id;
    q.push(i);
    instack[i]=1;
    for(int u=head[i]; ~u; u=edge[u].next)
    {
        j=edge[u].to;
        if(dfn[j]==0)
        {
            tarjan(j);
            if(low[i]>low[j])
                low[i]=low[j];
        }
        else if(instack[j]&&low[i]>low[j])
            low[i]=dfn[j];
    }
    if(dfn[i]==low[i])
    {
        ct++;
        do
        {
            j=q.top();
            q.pop();
            instack[j]=0;
            belong[j]=ct;
        }
        while(i!=j);
    }
}
int main()
{
    int t,i,u,v,sum1,sum2;
    cin>>t;
    while(t--)
    {
        clr(head,-1);
        clr(low,0);
        clr(dfn,0);
        clr(belong,0);
        clr(in,0);
        clr(to,0);
        while(!q.empty())
            q.pop();
        cin>>n>>m;
        for(i=0; i<m; i++)
        {
            cin>>u>>v;
            add_e(i,u,v);
        }
        id=ct=0;
        for(i=1; i<=n; i++)
        {
            if(!dfn[i])
                tarjan(i);
        }
        if(ct==1)
        {
            cout<<0<<endl;
            continue;
        }
        for(i=1; i<=ct; i++)
        {
            in[i]=to[i]=0;
        }
        for(i=0; i<m; i++)// 利用染色进行缩点   新的图的点的坐标为第i个强连通分量
        {
            if(belong[edge[i].st]!=belong[edge[i].to])
            {
                in[belong[edge[i].st]]++;
                to[belong[edge[i].to]]++;
            }
        }
        sum1=sum2=0;
        for(i=1; i<=ct; i++)
        {
            if(in[i]==0)
                sum1++;
            if(to[i]==0)
                sum2++;
        }
        cout<<max(sum1,sum2)<<endl;
    }
    return 0;
}
时间: 2024-10-05 05:10:56

hdu 2767 强连通缩点处理加边问题的相关文章

HDU 2767 强连通缩点

如A能证明B ,就建一条有向边A->B.对于一个能互相证明的一个集合,必然每个2个点都能相互到达,这样的一个集合就是一个强连通集合.我们可以把他们看成一个点,剩下的就是一个DAG图了. 如要都能相互到达,每个点必然出度 >=1, 入度>1 ..所以统计有多少没有入度的点和多少没有出度的点,他们中最大的就是需要添加的边了. VIEW CODE #include<cstdio> #include<cmath> #include<queue> #includ

hdu 4635(强连通+缩点)

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): 1381    Accepted Submission(s): 587 Problem Description Give a simple directed

HDU2767Proving Equivalences(强连通+缩点+ 至少加几条边让整个图变成强连通))

题意: 至少加几条边让整个图变成强连通. 思路:对于N个点的图,我们知道至少需要N条边才能使这个图强连通,现在我们先对题目的图计算一下强连通,对于已经在一个强连通的点,把他们看做为一个点,然后对新形成的图,计算出度,入度为0的最大值,因为,加一边,可以使入度,出度加一. #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<set> #in

The King’s Problem (hdu 3861 强连通缩点+最小路径覆盖)

The King's Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2085    Accepted Submission(s): 741 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cit

UVa 12167 &amp; HDU 2767 强连通分量 Proving Equivalences

题意:给出一个有向图,问最少添加几条有向边使得原图强连通. 解法:求出SCC后缩点,统计一下出度为0的点和入度为0的点,二者取最大值就是答案. 还有个特殊情况就是本身就是强连通的话,答案就是0. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <stack&

hdu 2767 Proving Equivalences 强连通缩点

给出n个命题,m个推导,问最少增加多少条推导,可以使所有命题都能等价(两两都能互推) 既给出有向图,最少加多少边,使得原图变成强连通. 首先强连通缩点,对于新图,每个点都至少要有一条出去的边和一条进来的边(这样才能保证它能到任意点和任意点都能到它) 所以求出新图中入度为0的个数,和出度为0的个数,添加的边就是从出度为0的指向入度为0的.这样还会有一点剩余,剩余的就乱连就行了. 所以只要求出2者的最大值就OK. #include <iostream> #include<cstring>

HDU 2767 Proving Equivalences(强连通 Tarjan+缩点)

HDU 2767 Proving Equivalences(强连通 Tarjan+缩点) ACM 题目地址:HDU 2767 题意: 给定一张有向图,问最少添加几条边使得有向图成为一个强连通图. 分析: Tarjan入门经典题,用tarjan缩点,然后就变成一个有向无环图(DAG)了. 我们要考虑的问题是让它变成强连通,让DAG变成强连通就是把尾和头连起来,也就是入度和出度为0的点. 统计DAG入度和出度,然后计算头尾,最大的那个就是所求. 代码: /* * Author: illuz <iil

hdu 2767 Proving Equivalences(强连通入门题)

1 /************************************************* 2 Proving Equivalences(hdu 2767) 3 强连通入门题 4 给个有向图,求至少加多少条边使得图是所有点都是强连通的 5 由a->b->c->a易知n个点至少要n条边,每个出度和入度都要大 6 于1.先求所有所有强连通分量,把每个强连通分量看成一个点 7 在找每个点的出度和入度,最后还差的出度和入度的最大值就是 8 答案. 9 10 ************

hdu 4635 强连通分量+缩点

http://acm.hdu.edu.cn/showproblem.php?pid=4635 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 graph is still a simple directed graph. Also, after you add