poj1236(强连通缩点)

传送门:Network of Schools

题意:一些学校联接在一个计算机网络上,学校之间存在软件支援协议,每个学校都有它应支援的学校名单(A学校支援学校B,并不表示B学校一定支援学校A)。当某校获得一个新软件时,无论是直接获得还是通过网络获得,该校都应立即将这个软件通过网络传送给它应支援的学校。因此,一个新软件若想让所有联接在网络上的学校都能使用,只需将其提供给一些学校即可。第一问:至少需要多少份软件,才能使得所有学校都能拥有软件;第二问:如果只用一份软件,那么需要添加多少条变,使得所有学校都能拥有软件。

分析:一个强连通分量中必定能相互连通,肯定能共享一个软件,因此第一问只需求入度为0的强连通分量个数即可。第二问求需要添加多少条变,使得整个图都成为一个强连通,即任意两个学校都可到达,那么取入度为0的个数a和出度为0的个数b中的最大值,因为强连通分量中必定不会有出度为0或入度为0的点,因此首先用边连接入度和出度为0的点,等其中一个完后再任意连接边把出度为0或入度为0的点补完。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 110
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
struct edge
{
    int v,next;
    edge(){}
    edge(int v,int next):v(v),next(next){}
}e[N*N];
int n,scc,step,top,tot;
int head[N],dfn[N],low[N],belong[N],Stack[N];
int in[N],out[N];
bool instack[N];
void init()
{
    tot=0;step=0;scc=0;top=0;
    FILL(head,-1);FILL(dfn,0);
    FILL(low,0);FILL(instack,false);
    FILL(in,0);FILL(out,0);
}
void addedge(int u,int v)
{
    e[tot]=edge(v,head[u]);
    head[u]=tot++;
}
void tarjan(int u)
{
    int v;
    dfn[u]=low[u]=++step;
    Stack[top++]=u;
    instack[u]=true;
    for(int i=head[u];~i;i=e[i].next)
    {
        v=e[i].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v])
        {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u])
    {
        scc++;
        do
        {
            v=Stack[--top];
            instack[v]=false;
            belong[v]=scc;
        }while(v!=u);
    }
}
void solve()
{
    for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
    if(scc==1)
    {
        printf("1\n0\n");
        return;
    }
    for(int u=1;u<=n;u++)
    {
        for(int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].v;
            if(belong[v]!=belong[u])
            {
                out[belong[u]]++;
                in[belong[v]]++;
            }
        }
    }
    int a=0,b=0;
    for(int i=1;i<=scc;i++)
    {
        if(!in[i])a++;
        if(!out[i])b++;
    }
    printf("%d\n%d\n",a,max(a,b));
}
int main()
{
    int u;
    while(scanf("%d",&n)>0)
    {
        init();
        for(int i=1;i<=n;i++)
        {
            while(scanf("%d",&u)&&u)
                addedge(i,u);
        }
        solve();
    }
}

时间: 2024-10-11 22:46:47

poj1236(强连通缩点)的相关文章

poj1236 强连通缩点

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

Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路

题目来源:Light OJ 1168 Wishing Snake 题意:有点难看懂题意 看了一个小时再加别人的代码才懂意思 从0开始 输入的那些每一对u v 都要经过 就是从0到到达那些点 思路:首先缩点 每一个强连通分量里面的点都是可达的 缩点后的图是有向无环图 如果从0这个强连通分量可以出去到2个强连通分量 那么这两个强连通分量是不可能相互可达 所以可行的方案就是所有的强连通分量连成一线 一个一个串起来 除了第一个 出度是1入度是0和最后一个出度是0入度是1 其他都是入度等于出度是1 特判只

强连通缩点— HDU1827

强连通缩点以后最终形成的是一棵树 我们可以根据树的性质来看缩点以后的强连通分量图,就很好理解了 /* gyt Live up to every day */ #include<cstdio> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<stack> #include<cstring> #include<

BZOJ 1051: [HAOI2006]受欢迎的牛 强连通缩点

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1051 题解: 强连通缩点得到DAG图,将图转置一下,对入度为零的点跑dfs看看能不能访问到所有的点. 代码: #include<iostream> #include<cstdio> #include<vector> #include<stack> #include<algorithm> #include<cstring> u

POJ3352Road Construction(边的双连通+强连通缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8673   Accepted: 4330 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

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

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

UVA - 11324 The Largest Clique 强连通缩点+记忆化dp

题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每个点的权值就是当前强连通分量点的个数. /* Tarjan算法求有向图的强连通分量set记录了强连通分量 Col记录了强连通分量的个数. */ #include <iostream> #include<cstring> #include<cstdio> #include<string> #include<algo

HDU 4971 A simple brute force problem. 强连通缩点+最大权闭合图

题意: 给定n个项目,m个技术难题 下面一行n个数字表示每个项目的收益 下面一行m个数字表示攻克每个技术难题的花费 下面n行第i行表示 第一个数字u表示完成 i 项目需要解决几个技术难题,后面u个数字表示需要解决的问题标号. 下面m*m的矩阵 (i,j) = 1 表示要解决j问题必须先解决i问题. (若几个问题成环,则需要一起解决) 问:最大收益. 思路: 先给问题缩点一下,每个缩点后的点权就是这个点内所有点权和. 然后跑一个最大权闭合图. #include<stdio.h> #include

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

poj2553 强连通缩点

The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 10114   Accepted: 4184 Description We will use the following (standard) definitions from graph theory. Let V be a nonempty and finite set, its elements being called ve