Special topic 2

A - Network of Schools

POJ - 1236

A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distribution list of school A, then A does not necessarily appear in the list of school B
You are to write a program that computes the minimal number of schools that must receive a copy of the new software in order for the software to reach all schools in the network according to the agreement (Subtask A). As a further task, we want to ensure that by sending the copy of new software to an arbitrary school, this software will reach all schools in the network. To achieve this goal we may have to extend the lists of receivers by new members. Compute the minimal number of extensions that have to be made so that whatever school we send the new software to, it will reach all other schools (Subtask B). One extension means introducing one new member into the list of receivers of one school.

Input

The first line contains an integer N: the number of schools in the network (2 <= N <= 100). The schools are identified by the first N positive integers. Each of the next N lines describes a list of receivers. The line i+1 contains the identifiers of the receivers of school i. Each list ends with a 0. An empty list contains a 0 alone in the line.

Output

Your program should write two lines to the standard output. The first line should contain one positive integer: the solution of subtask A. The second line should contain the solution of subtask B.

Sample Input

5
2 4 3 0
4 5 0
0
0
1 0

Sample Output

1
2

题解:对于子任务A就是求出连通块的数目,子任务B就是求最少添加多少条边能变成连通图(显然统计所有缩点里入度为0和出度为0的点的数目取最大那个便是)。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;
const int MAXN=20010;
const int MAXM=50010;
struct Edge
{
    int to ,nex;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top;
int scc;
bool instack[MAXN];
int num[MAXN];
int in[110],out[110];
void addedge(int u,int v){
    edge[tot].to=v;
    edge[tot].nex=head[u];head[u]=tot++;
}
void Tarjan(int u){
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    instack[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].nex){
        v=edge[i].to;
        if(!DFN[v]){
            Tarjan(v);
            if(Low[u]>Low[v]) Low[u]=Low[v];
        }
        else if (instack[v]&&Low[u]>DFN[v]){
            Low[u]=DFN[v];
        }
    }
    if(Low[u]==DFN[u]){
            scc++;
            do{
                v=Stack[--top];
                instack[v]=false;
                Belong[v]=scc;
                num[scc]++;
            }while(u!=v);
        }
}
void solve(int N)
{
    memset(DFN,0,sizeof DFN);
    memset(instack,false,sizeof instack);
    memset(num,0,sizeof num);
    Index =scc=top=0;
    for(int i=1; i<=N;i++)
    {
        if(!DFN[i]){
            Tarjan(i);
        }
    }
    for(int i=1;i<=N;i++){
        for(int k=head[i];k!=-1;k=edge[k].nex){
            int v=edge[k].to;
            if(Belong[v]!=Belong[i]){
                out[Belong[i]]++;
                in[Belong[v]]++;
            }
        }
    }
    int ans1=0;int ans2=0;
    for(int i=1;i<=scc;i++){
        if(!in[i]) ans1++;
        if(!out[i]) ans2++; 
    }
    if(scc==1){
        printf("1\n0\n");
    }
    else {
        ans2=max(ans1,ans2);
        printf("%d\n%d\n",ans1,ans2);
    }
}
void init(){
    tot =0;
    memset(head,-1,sizeof head);
}
int n;
int main()
{
    init();
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int v;
        while(scanf("%d",&v)&&v!=0){
            addedge(i,v);
        }
    }
    solve(n);
    //system("pause");
    return 0;
}

B - Network

UVA - 315

一个电话信号传输公司正在搭建一个新的电话电缆网络。他们想要连接从1到N标号的各个地点,标号不重复。电缆是双向作用的,在每个地方电缆都链接一个信号站。每个地点都有一个信号站。信号站与信号站之间可能通过若干个信号站实现连通。有的时候一个地点断电了那么部分信号站便都收不到信号。信号传输公司意识到这是因为一个地方信号站的失效而导致的其他地方信号站的失效,这样的信号站被称为中转站。现在信号传输公司想找出有多少个这样的中转站,请帮助他们。

Input

多样例输入,每个样例包括一个网络
第一行输入N(N<100),接下来的最多N行,每行第一个数表示一个地点,接下来的若干个数表示与改点连接有电缆的地点,当第一个数输入为0时,该样例输入结束。
当N为0 时,输入结束。

Output

对于每个样例输出中转站的个数。

Sample Input

5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0

Sample Output

1
2

题解:给出个无向图,求割点个数。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1001;
const int MAXM = 10001;
struct Edge{
    int to , nex;
}edge[MAXN];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN];
int Index,top;
bool Instack[MAXN];
bool cut[MAXN];
void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].nex=head[u];
    head[u]=tot++;
}
void Tarjan(int u,int pre)
{
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    Instack[u]=true;
    int son=0;
    //int pre_cnt=0;
    for(int i=head[u];i!=-1;i=edge[i].nex){
        v=edge[i].to;
        if(v==pre) {
            continue;
        }
        if(!DFN[v]){
            son++;
            Tarjan(v,u);
            if(Low[u]>Low[v]) Low[u]=Low[v];
            if(u!=pre&&Low[v]>=DFN[u]){
                cut[u]=true;
            }
        }
        else if(Low[u]>DFN[v]){
            Low[u]=DFN[v];
        }
    }
    if(u==pre&&son>1) cut[u]=true;
    Instack[u]=false;
    top--;
}
void solve(int N){
    memset(DFN,0,sizeof DFN);
    memset(Instack,false,sizeof Instack);
    memset(cut,false,sizeof cut);
    Index=top=0;
    for(int i=1;i<=N;i++){
        if(!DFN[i])
            Tarjan(i,i);
    }
    int ans=0;
    for(int i=1;i<=N;i++){
        if(cut[i]){
            ans++;
        }
    }
    printf("%d\n",ans);
}
void init()
{
    memset(head,-1,sizeof head);
    tot=0;
}
int n;
int main()
{
    while(scanf("%d",&n)&&n!=0){
        init();
        int u,v;
        while(scanf("%d",&u)&&u){
            char ov;
            while(scanf("%d%c",&v,&ov)){
                addedge(u,v);
                addedge(v,u);
                if(ov=='\n') break;
            }
        }
        solve(n);
    }
    //system("pause");
    return 0;
}

D - Network

POJ - 3694

网络管理员管理大型网络。该网络由N台计算机和成对计算机之间的M链路组成。任何一对计算机都通过连续的链接直接或间接连接,因此可以在任何两台计算机之间转换数据。管理员发现某些链接对网络至关重要,因为任何一个链接的故障都可能导致某些计算机之间无法转换数据。他把这种联系称为桥梁。他计划逐一添加一些新链接以消除所有桥梁。 您将通过在添加每个新链接后报告网络中的网桥数来帮助管理员。

输入

输入包含多个测试用例。每个测试用例以包含两个整数N(1≤N≤100,000)和M(N-1≤M≤200,000)的行开始。 以下M行中的每一行包含两个整数A和B(1≤A≠B≤N),表示计算机A和B之间的链接。计算机编号从1到N.保证任何两台计算机都连接在一起最初的网络。 下一行包含一个整数Q(1≤Q≤1,000),这是管理员计划逐个添加到网络的新链接数。 以下Q行的第i行包含两个整数A和B(1≤A≠B≤N),这是连接计算机A和B的第i个新链接。 最后一个测试用例后跟一行包含两个零的行。

输出

对于每个测试用例,打印一行包含测试用例编号(以1开头)和Q行,其中第i行包含一个整数,表示添加第一个i新链接后网络中的网桥数。在每个测试用例的输出后打印一个空行。

Sample Input

3 2
1 2
2 3
2
1 2
1 3
4 4
1 2
2 1
2 3
1 4
2
1 2
3 4
0 0

Sample Output

Case 1:
1
0

Case 2:
2
0

题意:给出一个有向图,并且每次给出新的边,求每次加边后图中的割边的数量。

题解:用tarjan算法缩点,并且根据算法里得到的dfn信息,对每次加入的两个点u,v寻找lca,则u到lca到v这条路径上的所有割边都减去即可。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int MAXN = 1000001;
const int MAXM = 2000001;
struct Edge{
    int to , nex;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN];
int Index,top;
bool bridge[MAXN];
int bre;
int fa[MAXN];
void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].nex=head[u];
    head[u]=tot++;
}
void Tarjan(int u,int pre)
{
    int v;
    Low[u]=DFN[u]=++Index;
    for(int i=head[u];i!=-1;i=edge[i].nex){
        v=edge[i].to;
        if(v==pre) {
            continue;
        }
        if(!DFN[v]){
            fa[v]=u;
            Tarjan(v,u);
            if(Low[u]>Low[v]) Low[u]=Low[v];
            if(Low[v]>DFN[u]){
                bre++;
                bridge[v]=true;
            }
        }
        else if(Low[u]>DFN[v]){
            Low[u]=DFN[v];
        }
    }
}
void solve(int N){
    memset(DFN,0,sizeof DFN);
    memset(bridge,false,sizeof bridge);
    Index=top=0;
    for(int i=1;i<=N;i++) fa[i]=i;
    for(int i=1;i<=N;i++){
        if(!DFN[i])
            Tarjan(i,i);
    }
}
void LCA(int u,int v)
{
    while(DFN[u]>DFN[v]){
        if(bridge[u]){
            bridge[u]=false;
            bre--;
        }
        u=fa[u];
    }
    while(DFN[v]>DFN[u]){
        if(bridge[v]){
            bridge[v]=false;
            bre--;
        }
        v=fa[v];
    }
    while(u!=v){
        if(bridge[v]) {
            bridge[v]=false;
            bre--;
        }
        if(bridge[u]){
            bridge[u]=false;
            bre--;
        }
        v=fa[v];
        u=fa[u];
    }
}
void init()
{
    memset(head,-1,sizeof head);
    bre=0;
    tot=0;
}
int n,m,q;
int main()
{
    int kcas=0;
    while(scanf("%d %d",&n,&m)!=EOF){
        if(n==0&&m==0) break;
        int x,y;
        init();
        for(int i=1;i<=m;i++){
            scanf("%d %d",&x,&y);
            addedge(x,y);
            addedge(y,x);
        }
        solve(n);
        scanf("%d",&q);
        printf("Case %d:\n",++kcas);
        for(int i=1;i<=q;i++){
            scanf("%d %d",&x,&y);
            LCA(x,y);
            printf("%d\n",bre);
        }
        printf("\n");
    }
    return 0;
}

先献上bin巨的blog:题解

G - Strongly connected

HDU - 4635

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 these edges, this graph must NOT be strongly connected.
A simple directed graph is a directed graph having no multiple edges or graph loops.
A strongly connected digraph is a directed graph in which it is possible to reach any node starting from any other node by traversing edges in the direction(s) in which they point.

Input

The first line of date is an integer T, which is the number of the text cases.
Then T cases follow, each case starts of two numbers N and M, 1<=N<=100000, 1<=M<=100000, representing the number of nodes and the number of edges, then M lines follow. Each line contains two integers x and y, means that there is a edge from x to y.

Output

For each case, you should output the maximum number of the edges you can add.
If the original graph is strongly connected, just output -1.

Sample Input

3
3 3
1 2
2 3
3 1
3 3
1 2
2 3
1 3
6 6
1 2
2 3
3 1
4 5
5 6
6 4

Sample Output

Case 1: -1
Case 2: 1
Case 3: 15
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100010;
const int maxm = 200010;
struct Edge{
    int  to, nex;
}edge[maxn];
int head[maxn],tot;
int Low[maxn],DFN[maxn],Stack[maxn],Belong[maxn];
int Index,top;
int scc;
bool Instack[maxn];
int num[maxn];
int in[maxn],out[maxn];
void addedge(int u,int v)
{
    edge[tot].to=v;edge[tot].nex=head[u];head[u]=tot++;
}
void Tarjan(int u)
{
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    Instack[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].nex){
        v=edge[i].to;
        if(!DFN[v]){
            Tarjan(v);
            if(Low[u]>Low[v]) Low[u]=Low[v];
        }
        else if(Instack[v]&&Low[u]>DFN[v])
            Low[u]=DFN[v];
    }
    if(Low[u]==DFN[u]){
        scc++;
        do
        {
            v=Stack[--top];
            Instack[v]=false;
            Belong[v]=scc;
            num[scc]++;
        } while (v!=u);
    }
}
void solve(int N)
{
    memset(DFN,0,sizeof DFN);
    memset(Instack,false,sizeof Instack);
    memset(num,0,sizeof num);
    Index=top=scc=0;
    for(int i=1;i<=N;i++)
    {
        if(!DFN[i])
            Tarjan(i);
    }
}
void init()
{
    tot=0;
    memset(head,-1,sizeof head);
}
int n,m,T;
ll ans=0;
int main()
{
    scanf("%d",&T);
    int kcase=0;
    while(T--)
    {
        scanf("%d %d",&n,&m);
        int x,y;
        init();
        for(int i=1;i<=m;i++){
            scanf("%d %d",&x,&y);
            addedge(x,y);
        }
        printf("Case %d: ",++kcase);
        solve(n);
        if(scc==1){
            printf("-1\n");
            continue ;
        }
        ll res=0;
        ans=1ll*(n*(n-1)-m);
        for(int i=1;i<=scc;i++)
        {
            in[i]=0;
            out[i]=0;
        }
        for(int i=1;i<=n;i++){
            for(int j=head[i];j!=-1;j=edge[j].nex){
                if(Belong[i]!=Belong[edge[j].to]){
                    out[Belong[i]]++;
                    in[Belong[edge[j].to]]++;
                }
            }
        }
        for(int i=1;i<=scc;i++){
            if(in[i]==0||out[i]==0){
                res=max(res,ans-1ll*(n-num[i])*num[i]);
            }
        }
        printf("%lld\n",res);
    }
   // system("pause");
    return 0;
}

 

这几行代码是使用ros::NodeHandle的param()函数从ROS参数服务器中获取参数的值。具体解释如下: - nh.param("scan_topic", scan_topic_, scan_topic)表示获取ROS参数服务器中名为"scan_topic"的参数值,并存储到scan_topic_变量中。如果获取失败,则使用scan_topic变量的默认值。 - nh.param("frame_id", frame_id_, frame_id)表示获取ROS参数服务器中名为"frame_id"的参数值,并存储到frame_id_变量中。如果获取失败,则使用frame_id变量的默认值。 - nh.param("serial_port", serial_port_, port)表示获取ROS参数服务器中名为"serial_port"的参数值,并存储到serial_port_变量中。如果获取失败,则使用port变量的默认值。 - nh.param("baud_rate", baud_rate_, 460800)表示获取ROS参数服务器中名为"baud_rate"的参数值,并存储到baud_rate_变量中。如果获取失败,则使用默认值460800。 - nh.param("angle_resolution", resolution_, 1.0)表示获取ROS参数服务器中名为"angle_resolution"的参数值,并存储到resolution_变量中。如果获取失败,则使用默认值1.0。 - nh.param("robot_radius", robot_radius_, 0.2)表示获取ROS参数服务器中名为"robot_radius"的参数值,并存储到robot_radius_变量中。如果获取失败,则使用默认值0.2。 - nh.param("center_x", center_x_, 0.0)表示获取ROS参数服务器中名为"center_x"的参数值,并存储到center_x_变量中。如果获取失败,则使用默认值0.0。 - nh.param("center_y", center_y_, 0.0)表示获取ROS参数服务器中名为"center_y"的参数值,并存储到center_y_变量中。如果获取失败,则使用默认值0.0。 - nh.param("rpm", rpm_, 600)表示获取ROS参数服务器中名为"rpm"的参数值,并存储到rpm_变量中。如果获取失败,则使用默认值600。 - nh.param("special_range", special_range_, 0.0)表示获取ROS参数服务器中名为"special_range"的参数值,并存储到special_range_变量中。如果获取失败,则使用默认值0.0。 - nh.param("angle_compensate", flag_angle_compensate, true)表示获取ROS参数服务器中名为"angle_compensate"的参数值,并存储到flag_angle_compensate变量中。如果获取失败,则使用默认值true。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值