【深搜】PAT甲级 1013 图 (计算连通分量)、牛客网 连通图、牛客网 欧拉回路、pat甲1079、甲1094

1013 Battle Over Cities (25 分)

It is vitally important to have all the cities connected by highways in a war. If a city is occupied by the enemy, all the highways from/toward that city are closed. We must know immediately if we need to repair any other highways to keep the rest of the cities connected. Given the map of cities which have all the remaining highways marked, you are supposed to tell the number of highways need to be repaired, quickly.

For example, if we have 3 cities and 2 highways connecting city​1​​-city​2​​ and city​1​​-city​3​​. Then if city​1​​ is occupied by the enemy, we must have 1 highway repaired, that is the highway city​2​​-city​3​​.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 3 numbers N (<1000), M and K, which are the total number of cities, the number of remaining highways, and the number of cities to be checked, respectively. Then M lines follow, each describes a highway by 2 integers, which are the numbers of the cities the highway connects. The cities are numbered from 1 to N. Finally there is a line containing K numbers, which represent the cities we concern.

Output Specification:

For each of the K cities, output in a line the number of highways need to be repaired if that city is lost.

Sample Input:

3 2 3
1 2
1 3
1 2 3

Sample Output:

1
0
0

#include <stdio.h>
#include <cstdio>
#include <string>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
using namespace std;
vector<vector<int>>graph(1005); //存储图!!!必须要写上大小,如括号里所示
bool visited[1005]={false};
void DFS(int v,int deleteV)
{
    visited[v]=true;
    for(int i=0;i<graph[v].size();i++)
    {
        int tmp=graph[v][i];
        if(!visited[tmp]&&tmp!=deleteV)
        {
            DFS(tmp,deleteV);
        }
    }
}
int main(){
    int n,m,k;
    scanf("%d %d %d",&n,&m,&k);
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        graph[a].push_back(b);
        graph[b].push_back(a);
    }
    for(int i=0;i<k;i++)
    {
        int x;
        scanf("%d",&x);
        int s=0;
        for(int j=0;j<1005;j++)
            visited[j]=false;
        for(int j=1;j<=n;j++)  //城市编号从1开始
            
        {
            if(!visited[j]&&j!=x)
            {
                DFS(j,x);
                s++;
            }
        }
        printf("%d\n",s-1);
    }
}

 

题目描述

https://www.nowcoder.com/practice/569e89823a5141fe8a11ab7d4da21edf?tpId=40&tqId=21506&tPage=9&rp=1&ru=%2Fta%2Fkaoyan&qru=%2Fta%2Fkaoyan%2Fquestion-ranking

    给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。

输入描述:

    每组数据的第一行是两个整数 n 和 m(0<=n<=1000)。n 表示图的顶点数目,m 表示图中边的数目。随后有 m 行数据,每行有两个值 x 和 y(0<x, y <=n),表示顶点 x 和 y 相连,顶点的编号从 1 开始计算。输入不保证这些边是否重复。

输出描述:

    对于每组输入数据,如果所有顶点都是连通的,输出"YES",否则输出"NO"。

示例1

输入

复制

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

输出

复制

NO
YES

#include <stdio.h>
#include <cstdio>
#include <string>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
using namespace std;
map<int,vector<int>>mmap;
int visited[10001];
void DFS(int v)
{
    visited[v]=1;
    vector<int>tmp=mmap[v];
    for(int i=0;i<tmp.size();i++)
    {
        if(visited[tmp[i]]==0)
        {
            DFS(tmp[i]);
        }
    }
}
int main(){
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            mmap[x].push_back(y);
            mmap[y].push_back(x);
        }
        for(int i=0;i<=10000;i++)
            visited[i]=0;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(visited[i]==0)
            {
                DFS(i);
                cnt++;
            }
        }
        if(cnt>1)
        {
            printf("NO\n");
        }
        else
        {
            printf("YES\n");
        }
    }
}

 

题目描述

https://www.nowcoder.com/practice/0ba5d8f525494a8787aaa9d53b5f9b9e?tpId=40&tqId=21447&tPage=6&rp=1&ru=%2Fta%2Fkaoyan&qru=%2Fta%2Fkaoyan%2Fquestion-ranking

    欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?

输入描述:

    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结束。

输出描述:

    每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。

示例1

输入

复制

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

输出

复制

1
0

#include <stdio.h>
#include <cstdio>
#include <string>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
using namespace std;
map<int,vector<int>>mmap;
int degree[1001];
int visited[1001];
void DFS(int v)
{
    visited[v]=1;
    vector<int>tmp=mmap[v];
    for(int j=0;j<tmp.size();j++)
    {
        if(!visited[mmap[v][j]])
        {
            visited[mmap[v][j]]=1;
            DFS(mmap[v][j]);
        }
    }
}
int main(){
    int n,m,mark[1001];
    while(scanf("%d %d",&n,&m)!=EOF)
    {
       
        for(int i=0;i<1001;i++)
            mark[i]=0;
        if(n==0) break;
        for(int i=0;i<m;i++)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            mark[a]=1;
            mark[b]=1;
            mmap[a].push_back(b);
            mmap[b].push_back(a);
            if(a!=b)
            {
                degree[a]++;
                degree[b]++;
            }
        }
        if(m==1) printf("0\n");  //注意只有边的时候肯定不行
        else
        {
        int cnt=0;
            int flag=0;
        for(int i=1;i<n;i++)
        {
            if(mark[i]==1)     //有些点没有边,不影响回路的产生
            {
                if(degree[i]%2!=0)  //欧拉回路:连通+每个点度为偶数
                {
                    flag=1;
                    break;
                }
                if(!visited[i])
               {
                visited[i]=1;
                DFS(i);
                cnt++;
               }
            }
        }
        if(cnt==1&&flag!=1)
        {
            printf("1\n");
        }
        else
        {
           printf("0\n");
        }
        }
    }
}

 

1079 Total Sales of Supply Chain (25 分)

A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyone involved in moving a product from supplier to customer.

Starting from one root supplier, everyone on the chain buys products from one's supplier in a price P and sell or distribute them in a price that is r% higher than P. Only the retailers will face the customers. It is assumed that each member in the supply chain has exactly one supplier except the root supplier, and there is no supply cycle.

Now given a supply chain, you are supposed to tell the total sales from all the retailers.

Input Specification:

Each input file contains one test case. For each case, the first line contains three positive numbers: N (≤10​5​​), the total number of the members in the supply chain (and hence their ID's are numbered from 0 to N−1, and the root supplier's ID is 0); P, the unit price given by the root supplier; and r, the percentage rate of price increment for each distributor or retailer. Then N lines follow, each describes a distributor or retailer in the following format:

K​i​​ ID[1] ID[2] ... ID[K​i​​]

where in the i-th line, K​i​​ is the total number of distributors or retailers who receive products from supplier i, and is then followed by the ID's of these distributors or retailers. K​j​​ being 0 means that the j-th member is a retailer, then instead the total amount of the product will be given after K​j​​. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the total sales we can expect from all the retailers, accurate up to 1 decimal place. It is guaranteed that the number will not exceed 10​10​​.

Sample Input:

10 1.80 1.00
3 2 3 5
1 9
1 4
1 7
0 7
2 6 1
1 8
0 9
0 4
0 3

Sample Output:

42.4

很简单的题目,由于给定的图是无环连通图,可以直接看成一棵树,用深度优先遍历或广度优先遍历求出每一个结点处的单价,然后与产品数对应相乘然后加和就可以得到结果了。

#include <stdio.h>
#include <cstdio>
#include <string>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
using namespace std;
vector<vector<int>>graph(100005);
double price[100001];
int product[100001];
double r;
void DFS(int v)
{
    vector<int>tmp=graph[v];
    for(int i=0;i<tmp.size();i++)
    {
        price[tmp[i]]=price[v]*(1+r/100);
        DFS(tmp[i]);
    }
}
int main(){
    int n;
    scanf("%d %lf %lf",&n,&price[0],&r);
    int str[100001];
    for(int i=0;i<n;i++)
    {
        scanf("%d",&str[i]);
        if(str[i]==0)
        {
            scanf("%d",&product[i]);
        }
        else
        {
            for(int j=0;j<str[i];j++)
        {
            int x;
            scanf("%d",&x);
            graph[i].push_back(x);
        }
        }
    }
    DFS(0);
    //int s=inner_product(price,price+n,product,0.0);
    double s=0;
    for(int i=0;i<n;i++)
    {
        if(str[i]==0)
        {
            s+=product[i]*price[i];
        }
    }
    printf("%.1f",s);
}

 

1094 The Largest Generation (25 分)

A family hierarchy is usually presented by a pedigree tree where all the nodes on the same level belong to the same generation. Your task is to find the generation with the largest population.

Input Specification:

Each input file contains one test case. Each case starts with two positive integers N (<100) which is the total number of family members in the tree (and hence assume that all the members are numbered from 01 to N), and M (<N) which is the number of family members who have children. Then M lines follow, each contains the information of a family member in the following format:

ID K ID[1] ID[2] ... ID[K]

where ID is a two-digit number representing a family member, K (>0) is the number of his/her children, followed by a sequence of two-digit ID's of his/her children. For the sake of simplicity, let us fix the root ID to be 01. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the largest population number and the level of the corresponding generation. It is assumed that such a generation is unique, and the root level is defined to be 1.

Sample Input:

23 13
21 1 23
01 4 03 02 04 05
03 3 06 07 08
06 2 12 13
13 1 21
08 2 15 16
02 2 09 10
11 2 19 20
17 1 22
05 1 11
07 1 14
09 1 17
10 1 18

Sample Output:

9 4

DFS:

#include <stdio.h>
#include <cstdio>
#include <string>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
using namespace std;
vector<vector<int>>tree(1005);
int l[10001];
int visited[1001];
int DFS(int v,int level)
{
    visited[v]=1;
    l[level]++;   //存储每层下结点个数,节点数在for循环外面增加
    vector<int>tmp=tree[v];
    for(int i=0;i<tmp.size();i++)
    {
        if(!visited[tmp[i]])
        {
            visited[tmp[i]]=1;
            DFS(tmp[i],level+1); //层数在for循环里增加
        }
    }
    return level;
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int id1,k,id[1001];
        scanf("%d %d",&id1,&k);
        for(int j=1;j<=k;j++)
        {
            scanf("%d",&id[j]);
            tree[id1].push_back(id[j]);
        }
    }
    for(int i=0;i<1001;i++)
        visited[i]=0;
    int s=DFS(1,1);
    int max1=0,t=0;
    for(int i=1;i<=n;i++)
    {
        if(l[i]>max1)
        {
            max1=l[i];
            t=i;
        }
    }
    printf("%d %d",max1,t);
}

 

BFS:

#include <stdio.h>
#include <cstdio>
#include <string>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
using namespace std;
vector<vector<int>>tree(1005);
int l[10001];
int level[10001];
int visited[10001];
void BFS(int v)
{
    visited[v]=1;
    queue<int>q;
    q.push(v);
    while(!q.empty())
    {
        v=q.front();
        q.pop();
        l[level[v]]++;   //节点数在for循环外面增加
        vector<int>tmp=tree[v];
        for(int i=0;i<tmp.size();i++)
        {
            level[tmp[i]]=level[v]+1;  //层数在for循环里增加
            if(!visited[tmp[i]])
            {
                visited[tmp[i]]=1;
                q.push(tmp[i]);
            }
        }
    }
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int id1,k,id[1001];
        scanf("%d %d",&id1,&k);
        for(int j=1;j<=k;j++)
        {
            scanf("%d",&id[j]);
            tree[id1].push_back(id[j]);
        }
    }
    for(int i=0;i<10001;i++)
    {
        visited[i]=0;
        level[i]=1;
    }
    BFS(1);
    int max1=0,t=0;
    for(int i=1;i<=n;i++)
    {
        if(l[i]>max1)
        {
            max1=l[i];
            t=i;
        }
    }
    printf("%d %d",max1,t);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值