hdu(4635)

给一张有向图,问在这张图中最多还能添加多少条边,使得添加完以后图仍然不强连通。

tarjan缩点完以后进行乘法技术原理。记录每个强连通分量的入度和出度,只有入度或出度为零的点才可以当做最后被孤立的那个连通分量,其余剩下的所有连通分量全部通过加边变成一个连通块,然后枚举被分出来的那个连通块,更新最大答案。

#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int inf = 1<<20;
const int maxn = 100005;
int n,m;
struct node
{
    int to;
    int next;
    node(){}
    node(int a,int b):to(a),next(b){}
}edge[maxn<<1];
int head[maxn],dfn[maxn],low[maxn],vis[maxn],belong[maxn],ret[maxn],in[maxn],out[maxn],key[maxn];
int tot,ti,cnt;
stacks;
void tarjan(int u)
{
    low[u] = ++ti; dfn[u] = ti; s.push(u); vis[u] = 1;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v = edge[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u],low[v]);
        }
        else if(vis[v]==1)
        {
            low[u] = min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        cnt++; int y;
        do{
            y = s.top(); s.pop();
            belong[y] = cnt;
            ret[cnt] ++;
            vis[y] = 2;
        }while(y!=u);
    }
}
int main()
{
    int cases,u,v,t=1;
    scanf("%d",&cases);
    while(cases--)
    {
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head)); tot = 0;
        for(int i=0;i

你可能感兴趣的:(图论)