2018年全国多校算法寒假训练营练习比赛(第四场)(图论)

20 篇文章 0 订阅
19 篇文章 0 订阅

链接:https://www.nowcoder.net/acm/contest/76/A
来源:牛客网

随着海上运输石油泄漏的问题,一个新的有利可图的行业正在诞生,那就是撇油行业。如今,在墨西哥湾漂浮的大量石油,吸引了许多商人的目光。这些商人们有一种特殊的飞机,可以一瓢略过整个海面20米乘10米这么大的长方形。(上下相邻或者左右相邻的格子,不能斜着来)当然,这要求一瓢撇过去的全部是油,如果一瓢里面有油有水的话,那就毫无意义了,资源完全无法利用。现在,商人想要知道,在这片区域中,他可以最多得到多少瓢油。

地图是一个N×N的网络,每个格子表示10m×10m的正方形区域,每个区域都被标示上了是油还是水
输入描述:
测试输入包含多条测试数据
测试数据的第一行给出了测试数据的数目T(T<75)
每个测试样例都用数字N(N<50)来表示地图区域的大小,接下来N行,每行都有N个字符,其中符号’.’表示海面、符号’#’表示油面。
输出描述:
输出格式如下“Case X: M”(X从1开始),M是商人可以最多得到的油量。
示例1
输入
1
6
……
.##…
……
.#..#.
.#..##
……
输出
Case 1: 3

分析: 求有多少个 两个相邻的’#’
dfs
不过这题目的数据好像比较弱,, 发现自己写错了还能够A。。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <map>
#include <set>
#include <bitset>
#include <cctype>
#include <cstdlib>
#include <queue>
#include <cmath>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <sstream>
#include <functional>
#include <algorithm>
using namespace std;

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)
#define dec(i,n,a) for(int i=n;i>=a;i--)///[n,a]
#define pb push_back
#define fi first
#define se second
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const double PI=acos(-1.0);
const double E=2.718281828459045;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const int MOD=258280327;
const int N=50+5;
const ll maxn=1e6+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
int n,ans;
char a[N][N];
bool vis[N][N];
bool in(int x,int y)
{
    if(x>=0&&x<n&&y>=0&&y<n) return true;
    return false;
}
bool dfs(int x,int y)
{
    rep(i,0,4)
    {
        int nx=x+dir[i][0],ny=y+dir[i][1];
        if(in(nx,ny) && a[nx][ny]=='#')
        {
            a[x][y]='.';
            if(!dfs(nx,ny))
            {
                a[nx][ny]='#';
                ans++;
                return true;
            }
            a[x][y]='#';
        }
    }
    return false;
}
int main()
{
    int T;
    scanf("%d",&T);
    rep(cas,0,T)
    {
        scanf("%d",&n);
        ans=0;
        mem(vis,0);
        rep(i,0,n) scanf("%s",a[i]);
        rep(i,0,n)
        {
            rep(j,0,n)
            {
                if(a[i][j]=='#')
                    dfs(i,j);
            }
        }
        printf("Case %d: %d\n",cas+1,ans);
    }
    return 0;
}

链接:https://www.nowcoder.net/acm/contest/76/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld
题目描述
随着如今社会的不断变化,交通问题也变得越来越重要,所以市长决定建设一些公路来方便各个城市之间的贸易和交易。虽然市长的想法很好,但是他也遇到了一般人也经常头疼的问题,那就是手头的经费有限……在规划过程中,设计师们已经预算出部分城市之间建设公路的经费需求。现在市长想知道,它能不能将他的m个城市在有限的经费内实现公路交通。如果可以的话,输出Yes,否则输出No(两个城市不一定要直接的公路相连,间接公路到达也可以。)

输入描述:
测试输入包含多条测试数据
每个测试数据的第1行分别给出可用的经费c(<1000000),道路数目n(n<10000),以及城市数目m(<100)。
接下来的n行给出建立公路的成本信息,每行给出三个整数,分别是相连的两个城市v1、v2(0<v1,v2<=m)以及建设公路所需的成本h(h<100)。
输出描述:
对每个测试用例,输出Yes或No。
示例1
输入
20 10 5
1 2 6
1 3 3
1 4 4
1 5 5
2 3 7
2 4 7
2 5 8
3 4 6
3 5 9
4 5 2
输出
Yes
示例2
输入
10 2 2
1 2 5
1 2 15
输出
Yes
备注:
两个城市之间可能存在多条线路

分析: 最小生成树。。 kruskal算法(并查集+排序)

#include <cstdio>
#include <iostream>
#include <cstring>
#include <map>
#include <set>
#include <bitset>
#include <cctype>
#include <cstdlib>
#include <queue>
#include <cmath>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <sstream>
#include <functional>
#include <algorithm>
using namespace std;

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)
#define dec(i,n,a) for(int i=n;i>=a;i--)///[n,a]
#define pb push_back
#define fi first
#define se second
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const double PI=acos(-1.0);
const double E=2.718281828459045;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const int MOD=258280327;
const int N=1e2+5;
const ll maxn=1e6+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
int par[N];
struct Node
{
    int u,v,w;
    bool operator < (const Node& m)const
    {
        return w<m.w;
    }
} a[maxn];
int Find(int x)///找根结点
{
    int r=x;
    while(par[r]!=r)
        r=par[r];
    int t=x;
    while(t!=r)
    {
        int fa=par[t];
        par[t]=r;
        t=fa;
    }
    return r;
}
bool unite(int x,int y)//合并
{
    x=Find(x),y=Find(y);
    if(x!=y)
    {
        par[x]=y;
        return true;
    }
    return false;
}
int main()
{
    int n,k=0,m,c;
    while(~scanf("%d%d%d",&c,&n,&m))
    {
        int num=0;
        for(int i=1; i<=m; i++)
            par[i]=i;
        for(int i=1; i<=n; i++)
            scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
        sort(a,a+n);
        int ans=0;
        for(int i=1; i<=n; i++)
        {
            int u=a[i].u,v=a[i].v;
            if(unite(u,v)) ans+=a[i].w;
        }
        printf("%s\n",ans>c?"No":"Yes");
    }
    return 0;
}

链接:https://www.nowcoder.net/acm/contest/76/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给你两个升序排列的集合,求出两个集合的交集。

输入描述:
有多个测试用例,输入到文件结束。
对于每一个测试用例:
第一行输入两个整数n,m(0<n,m<=1000000),分别代表第一个集合和第二个集合的元素的数量。
第二行输入n个整数,表示第一个集合中的元素,元素之间用空格隔开。
第三行输入m个整数,表示第二个集合中的元素,元素之间用空格隔开。
两个集合中的元素范围在[-1000000000,1000000000]区间内。
输出描述:
每个测试用例用一行来输出两个集合的交集的所有元素(元素用空格隔开且按升序排列),若交集为空则输出”empty”。
示例1
输入
2 3
1 3
1 2 3
输出
1 3
备注:
交集为空的情况下,输出”empty”

分析: 直接用set_intersection 内存超限。。 (喔不是用了vector,最多不就10^6个元素?
暴力过了

MLE代码:

set<int>st1,st2;
vector<int>ANS;
int main(void)
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        int x;
        while(n--) scanf("%d",&x),st1.insert(x);
        while(m--) scanf("%d",&x),st2.insert(x);
        set_intersection(st1.begin(),st1.end(),st2.begin(),st2.end(),inserter(ANS,ANS.begin()));
        int sz=ANS.size();
        if(!sz) puts("empty");
        else
        {
            for(int i=0; i<sz-1; i++) printf("%d ",ANS[i]);
            printf("%d\n",ANS[sz-1]);
        }
        st1.clear();
        st2.clear();
       // printf("%d %d\n",st1.size(),st2.size());
    }
    return 0;
}

AC代码: 【暴力】

const int N=1e6+5;
const ll maxn=5e4;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
int A[N],B[N],result[N];
int main(void)
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        rep(i,0,n) scanf("%d",&A[i]);
        rep(i,0,m) scanf("%d",&B[i]);
        int i = 0, j = 0;
        int cnt = 0;
        while(i < n && j < m)
        {
            if(A[i] == B[j])
            {
                result[cnt] = A[i];
                i++;
                j++;
                cnt++;
            }
            else if(A[i] < B[j])
            {
                i++;
            }
            else
            {
                j++;
            }
        }
        if(!cnt) puts("empty");
        else
        {
            for(int i=0; i<cnt-1; i++) printf("%d ",result[i]);
            printf("%d\n",result[cnt-1]);
        }
    }
    return 0;
}

链接:https://www.nowcoder.net/acm/contest/76/F
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
从实验室出来后,你忽然发现你居然把自己的电脑落在了实验室里,但是实验室的老师已经把大门锁上了。更糟的是,你没有那个老师的电话号码。你开始给你知道的所有人打电话,询问他们有没有老师的电话,如果没有,他们也会问自己的同学来询问电话号码。那么,你能联系到老师并且拿到电脑吗。
输入描述:
存在多组测试样例
每组样例的第一行分别是两个整数n(1

const int N=50+5;
const ll maxn=5e4;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
bool d[N][N];
int n,m;
void floyd()
{
    for(int k=1; k<=n; k++)
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                d[i][j]=d[i][j]||(d[i][k]&&d[k][j]);
}
int main()
{
    //fre;
    while(~scanf("%d%d",&n,&m))
    {
        mem(d,0);
        rep(i,0,m)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            d[x][y]=1;
            //d[y][x]=1;
        }
        floyd();
        //for(int i=1;i<=n;i++) printf("d[1][%d]=%d\n",i,d[1][i]);
        if(d[1][n]) puts("Yes");
        else puts("No");
    }
    return 0;
}

链接:https://www.nowcoder.net/acm/contest/76/H
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
老李见和尚赢了自己的酒,但是自己还舍不得,所以就耍起了赖皮,对和尚说,光武不行,再来点文的,你给我说出来1-8的全排序,我就让你喝,这次绝不耍你,你能帮帮和尚么?
输入描述:

输出描述:
1~8的全排列,按照全排列的顺序输出,每行结尾无空格。
示例1
输入
No_Input
输出
Full arrangement of 1~8
备注:
1~3的全排列 :
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

分析:STL中的next_permutation()函数

int main()
{
    int a[8];
    rep(i,0,8) a[i]=i+1;
    do
    {
        rep(i,0,8) printf("%d%c",a[i],i==7?'\n':' ');
    }
    while(next_permutation(a,a+8));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值