CCPC-Wannafly Summer Camp 2019 全记录

// 7.19-7.29 东北大学秦皇岛校区十天训练营,题目都挂在了Vjudge上。训练期间比较忙,没空更博总结,回来继续补题消化。

// https://vjudge.net/contest/312902

https://vjudge.net/contest/313217

https://vjudge.net/contest/313584

https://vjudge.net/contest/314412

https://vjudge.net/contest/314730

https://vjudge.net/contest/314974

Day1

这天授课主题是简单图论,节奏挺好,wls两小时理完图论里的基本知识点。

下午的赛题就偏入门了(简单图论无疑),只涉及到最短路问题和简单的搜索以及一些奇怪的技巧。(差分约束呢?最小生成树呢?强连通分量呢?)

A - Jzzhu and Cities (补)

把火车线路加上跑Dijkstra就好了,标记火车线路,相等时也要push。在最短路上的火车线路不能被取消,剩下的全部能取消。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 200010;
struct Edge {
    int to;
    bool istrain;
    ll w;
    Edge(int v, bool is, ll ww):to(v), istrain(is), w(ww){}
    bool operator<(const Edge& a)const {
        if(w==a.w) return istrain;  // 非火车节点先更新
        return w > a.w;
    }
};
vector<Edge> G[maxn];

bool vis[maxn];
int d[maxn];

int Dijkstra() {
    memset(d, 0x3f, sizeof(d));
    memset(vis, 0, sizeof(vis));
    d[1] = 0;
    int res = 0;

    priority_queue<Edge> q;
    q.push(Edge(1, 0, 0));
    while(!q.empty()) {
        Edge tmp = q.top(); q.pop();
        int u = tmp.to;
        if(vis[u]) continue;

        vis[u] = 1;
    //    d[u] = tmp.w;
        if(tmp.istrain) ++res;

        for(int i=0;i<G[u].size();i++) {
            int v = G[u][i].to;
            if(!vis[v] && d[v]>=d[u]+G[u][i].w) {
                d[v] = d[u] + G[u][i].w;
                q.push(Edge(v, G[u][i].istrain, d[v]));
            }
        }

    }
    return res;

}

int main() {
    int n, m, k;
    cin>>n>>m>>k;
    int u, v, w;
    for(int i=0;i<m;i++) {
        scanf("%d %d %d", &u, &v, &w);
        G[u].push_back(Edge(v, 0, w));
        G[v].push_back(Edge(u, 0, w));
    }
    for(int i=0;i<k;i++) {
        scanf("%d %d", &v, &w);
        G[1].push_back(Edge(v, 1, w));
        // G[v].push_back(Edge(1, 1, w));
    }

    printf("%d\n", k-Dijkstra());

    return 0;
}

B - Phillip and Trains

BFS 注意打标记!!!(虽然只是3*100的地图也要爆内存!)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n, k, sx;
char mp[3][110];
bool vis[3][110];
struct node {
    int x, y;
    node(int _x, int _y):x(_x), y(_y) {}
};

bool check(int x, int y) {
    if(x<0 || x>2)
        return false;
    if(y>=n)
        return true;
    if(mp[x][y]==‘.‘)
        return true;

    return false;
}

bool bfs() {
    queue<node> q;
    q.push(node(sx, 0));

    while(q.size()) {
        node now = q.front(); q.pop();
        if(now.y>=n) {
            return true;
        }

    //    printf("(%d,%d) -> ", now.x, now.y);

        int nx = now.x, ny = now.y+1;
        if(!check(nx, ny))  continue; // 向右走一步

        for(int i=-1;i<=1;i++) {      // 尝试三个方向移动
            nx = now.x + i;
            if(check(nx, ny) && check(nx, ny+1) && check(nx, ny+2) && !vis[nx][ny+2]) {
                q.push(node(nx, ny+2));
                vis[nx][ny+2] = 1;
            }
        }
    }
    return false;
}

int main() {
    int t; cin>>t;
    while(t--) {
        scanf("%d %d", &n, &k);
        getchar();
        memset(vis, 0, sizeof(vis));
        for(int i=0;i<3;i++) {
            scanf("%s", mp[i]);

            if(mp[i][0]==‘s‘)
                sx = i;

        }
        printf("%s\n", bfs()?"YES":"NO");
    }

    return 0;
}

C - A Mist of Florescence (补)

构造题,技巧就是设计井字形的连通块,把其他颜色块涂到井字的格子上。

#include<iostream>
#include<cstdio>
using namespace std;

int a, b, c, d;
char ans[50][50];
void solve() {
    for(int i=1;i<=12;i++) {
        for(int j=1;j<50;j++) {
            if(i%2==1 && j%2==1 && a) ans[i][j] = ‘A‘, --a;
            else ans[i][j] = ‘D‘;
        }
    }

    for(int i=13;i<=24;i++) {
        for(int j=1;j<50;j++) {
            if(i%2==1 && j%2==1 && b) ans[i][j] = ‘B‘, --b;
            else ans[i][j] = ‘D‘;
        }
    }

    --c;
    --d;
    for(int i=25;i<=36;i++) {
        for(int j=1;j<50;j++) {
            if(i%2==1 && j%2==1 && c) ans[i][j] = ‘C‘, --c;
            else ans[i][j] = ‘D‘;
        }
    }

    for(int j=1;j<50;j++) {
        ans[37][j] = ‘C‘;
    }

    for(int i=38;i<50;i++) {
        for(int j=1;j<50;j++) {
            if(i%2==1 && j%2==1 && d) ans[i][j] = ‘D‘, --d;
            else ans[i][j] = ‘C‘;
        }
    }

}
int main() {
    cin>>a>>b>>c>>d;
    solve();
    printf("49 49\n");
    for(int i=1;i<50;i++) {
        for(int j=1;j<50;j++)
            printf("%c", ans[i][j]);
        printf("\n");
    }

    return 0;
}

E - Igor In the Museum

DFS到墙的边界 对每块编号!

#include<iostream>
#include<cstdio>
using namespace std;

int n, m, k;
char mp[1010][1010];
int v[1010][1010], id;  // v[i][j]: mp[i][j]的分类编号   id: 当前编号
int res[1010*1010];        // res[id]: 第id块的答案

const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};

int ans;
void dfs(int x, int y) {
    if(mp[x][y]==‘*‘) {
        ans++;
        return;
    }
    v[x][y] = id;
    for(int i=0;i<4;i++) {
        int nx = x+dx[i], ny = y+dy[i];
        if(nx>=0 && nx<m && ny>=0 && ny<n && !v[nx][ny]) {
            dfs(nx, ny);
        }
    }
}
int main() {
    scanf("%d %d %d", &m, &n, &k);
    getchar();
    for(int i=0;i<m;i++) {
        scanf("%s", mp[i]);
    }

    for(int i=0;i<m;i++) {
        for(int j=0;j<n;j++) {
            if(mp[i][j]==‘.‘ && !v[i][j]) {
                ++id;
                ans = 0;
                dfs(i, j);
                res[id] = ans;
            }
        }
    }

    while(k--) {
        int x, y;
        scanf("%d %d", &x, &y);
        printf("%d\n", res[v[x-1][y-1]]);
    }

    return 0;
}

F - The Cild and Toy (补)

贪心!由于每去掉一个点,等价于去掉了所有与它相连的边,就是问去掉全部边的最小代价。答案当然就是每条边两个节点权值小的那头的总和。都不用建图!!

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 1010;
int n, m;
int w[maxn];

int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++) {
        scanf("%d", &w[i]);
    }
    int u, v, ans = 0;
    for(int i=0;i<m;i++) {
        scanf("%d %d", &u, &v);
        ans += min(w[u], w[v]);
    }
    printf("%d\n", ans);

    return 0;
}

G - New Year Permutation

对连通部分排序就完事了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int n, num[310], id;
int mp[310][310];
bool vis[310];

int ans[310];
struct list {
    vector<int> num;
    vector<int> id;
}L[310];

void dfs(int x, int id) {
    vis[x] = 1;

    L[id].num.push_back(num[x]);
    L[id].id.push_back(x);

    for(int i=1;i<=n;i++) {
        if(mp[x][i]) {
            if(!vis[i])
                dfs(i, id);
        }
    }
}

int main() {
    cin>>n;
    for(int i=1;i<=n;i++) {
        scanf("%d", &num[i]);
    }
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            scanf("%1d", &mp[i][j]);
        }
    }

    for(int i=1;i<=n;i++) {
        if(!vis[i])
            dfs(i, ++id);
    }

    for(int i=1;i<=id;i++) {
        // for(int j=0;j<L[i].num.size();j++) {
        //     printf("%d:%d ", L[i].num[j], L[i].id[j]);
        // }
        // cout<<endl;

        sort(L[i].num.begin(), L[i].num.end());
        sort(L[i].id.begin(), L[i].id.end());

        for(int j=0;j<L[i].num.size();j++) {
            ans[L[i].id[j]] = L[i].num[j];
        }
    }
    for(int i=1;i<=n;i++) {
        printf("%d%c", ans[i], i!=n?‘ ‘:‘\n‘);
    }
    return 0;
}

H - Alyona and the Tree (补)

从根开始dfs就好,每个节点为max(0LL, now+w[i])

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 100010;
typedef long long ll;

struct Edge {
    int to;
    ll w;
    Edge(int v, ll ww):to(v), w(ww) {}
};
vector<Edge> G[maxn];
int n, vw[maxn];
int ans;
void dfs(int u, int fa, ll now) {
    for(int i=0;i<G[u].size();i++) {
        int v = G[u][i].to;
        if(v!=fa) {
            if(vw[v]>=now+G[u][i].w) {
                --ans;
                // printf("%d->%d\n", u, v);
                dfs(v, u, max(now+G[u][i].w, 0LL));
            }
        }
    }

}

int main() {
    cin>>n; ans = n;
    for(int i=1;i<=n;i++) {
        scanf("%d", &vw[i]);
    }
    int u, w;
    for(int i=2;i<=n;i++) {
        scanf("%d %d", &u, &w);
        G[i].push_back(Edge(u, w));
        G[u].push_back(Edge(i, w));
    }

    dfs(1, -1, 0);
    printf("%d\n", ans-1);
    return 0;
}

L - Love Triangle

假的三元环??

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 5010;
int n, tot;
int love[maxn], low[maxn];
bool vis[maxn];
bool ans;
void dfs(int u) {
    if(ans) return;

    vis[u] = true;
    low[u] = ++tot;
    int v = love[u];
    if(v && !vis[v]) {
        dfs(v);
        if(love[v] && low[love[v]]==low[u]+2 && love[love[v]]==u) {
            ans = true;
            return;
        }
    }
}

int main() {
    cin>>n;
    for(int i=1;i<=n;i++) {
        scanf("%d", &love[i]);
    }
    ans = false;
    for(int i=1;i<=n;i++) {
        if(!vis[i] && !ans)
            dfs(i);
    }
    printf("%s\n", ans?"YES":"NO");
    return 0;
}

N - News Distribution

并查集

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 500100;
int n, m;
int fa[maxn];
int g[maxn], cnt[maxn];

int Find(int x) {
    return fa[x]==x?x:(fa[x]=Find(fa[x]));
}

void Union(int x, int y) {
    int a = Find(x);
    int b = Find(y);
    if(a==b) return;
    fa[a] = b;
}

int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++) fa[i] = i;
    while(m--) {
        int k;
        scanf("%d", &k);
        for(int i=0;i<k;i++) {
            scanf("%d", &g[i]);
        }
        for(int i=1;i<k;i++) {
            Union(g[0], g[i]);
        }
    }
    for(int i=1;i<=n;i++) {
        cnt[Find(i)]++;
    }
    for(int i=1;i<=n;i++) {
        printf("%d%c", cnt[Find(i)], i!=n?‘ ‘:‘\n‘);
    }
    return 0;
}

O - NP-Hard Problem (补)

二分图裸题。。。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 100010;
int n, m;
vector<int> G[maxn];
int deg[maxn];
int id[maxn];
vector<int> ans[2];
bool dfs(int u) {
    for(int i=0;i<G[u].size();i++) {
        int v = G[u][i];
        if(!id[v]) {
            id[v] = 3 - id[u];
            if(id[v]==1)
                ans[0].push_back(v);
            else
                ans[1].push_back(v);
            if(!dfs(v)) return false;
        } else if(id[v]==id[u]) return false;
    }
    return true;
}

int main() {
    cin>>n>>m;
    int u, v;
    for(int i=0;i<m;i++) {
        scanf("%d %d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
        ++deg[u];
    }
    for(int i=1;i<=n;i++) {
        if(!deg[i]) continue;

        if(!id[i]) {
            id[i] = 1;
            ans[0].push_back(i);
            if(!dfs(i))
                return 0 * printf("-1\n");
        }

    }

    for(int k=0;k<=1;k++) {
        printf("%d\n", ans[k].size());
        for(int i=0;i<ans[k].size();i++) {
            printf("%d%c", ans[k][i], i==ans[k].size()-1?‘\n‘:‘ ‘);
        }
    }

    return 0;
}

Day2

Day3

Day4

Day5

Day6

原文地址:https://www.cnblogs.com/izcat/p/11274543.html

时间: 2024-10-07 22:39:33

CCPC-Wannafly Summer Camp 2019 全记录的相关文章

2019 wannafly winter camp

2019 wannafly winter camp Name Rank Solved A B C D E F G H I J K day1 9 5/11 O O O O O day2 5 3/12 O O O day3 6 5/10 O O O O O day4 5 6/11 O O O O O O day5 3 4/10 O O O O day7 7 7/10 O O O O O O O day8 7 5/10 O O O O O 原文地址:https://www.cnblogs.com/wu

Orange&#39;s 自己动手写操作系统 第一章 十分钟完成的操作系统 U盘启动 全记录

材料: 1 nasm:编译汇编源代码,网上很多地方有下 2  WinHex:作为windows系统中的写U盘工具,需要是正版(full version)才有写的权限,推荐:http://down.liangchan.net/WinHex_16.7.rar 步骤: 1 编译得到引导程序的机器代码.用命令行编译汇编源代码:name boot.asm -o boot.bin,其中boot.bin文件产生在命令行的当前目录中. 2 将引导程序写入到U盘引导盘的第一个扇区的第一个字节处(后),即主引导区.

CentOS6.5_Nginx1.40_Php5.57_MySQL5.5.35编译安装全记录

环境说明:CentOS 6.5 32位  PHP Version 5.5.7  mysql version _5.6.16 一.准备工作 配置防火墙,允许防火墙通过22(sshd).80(WEB).3306(MYSQL)端口iptables -A INPUT -p tcp --dport 80 -j ACCEPTiptables -A INPUT -p tcp --dport 3306 -j ACCEPTiptables -A INPUT -p tcp --dport 22 -j ACCEPTi

C#打包制作安装程序过程全记录

该文是根据网上的文章并结合自己实际打包的过程而整理的. 开发平台:VisualStudio2005中文版. 步骤如下: 1. 创建一个安装向导项目或安装部署项目 新建项目-〉其他项目类型-〉安装与部署-〉安装向导(或安装部署),如命名为setup. 2. 将要打包的项目导入到这个安装项目中,有两种方式:   第一种,自动方式,在解决方案上右击-〉添加-〉现有项目-〉选择你要打包的项目,这样就会把这个项目添加到该解决方案中来,   然后在安装项目setup上右击-〉添加-〉项目输出-〉主输出,在项

MonkeyImage API 实践全记录

1.    背景 鉴于网上使用MonkeyImage的实例除了方法sameAs外很难找到,所以本人把实践各个API的过程记录下来然自己有更感性的认识,也为往后的工作打下更好的基础.同时也和上一篇文章<MonkeyDevcie API 实践全记录>起到相互呼应的作用. 因为并没有MonkeyRunner的项目背景,所以这里更多的是描述各个API是怎么一回事,而不是描述在什么场景下需要用到.也就是说是去回答What,而不是How. 首先我们先看下官方给出的MonkeyImage的API描述,对比我

WEB应用打成jar包全记录

内容属原创,转载请注明出处 题外 由于项目的需求—不管是怎么产生的这个需求—总之,需要支持把一个web应用打成jar包供其他应用使用,这就有了下面的过程. 这个过程里用到了Spring和SpringMVC(用到的版本是3.1.4,后面略过此描述)的若干东东,如果不用这玩意的,请飘过. 要做些什么? 需要打包的这个Web应用包含下面这些内容: 静态资源,含 js.css.image 页面文件:jsp Jsp标签,含 tld文件和若干java代码 基于SpringMVC的其他若干Control和Se

内存数据库Timesten安装过程全记录

[[email protected] timesten]# su - tt [[email protected] ~]$ cd /timesten/linux8664/ [[email protected] linux8664]$ ls 3rdparty  doc  install.pl  LINUX8664  README.html  setup.sh  uninst.sh [[email protected] linux8664]$ ./setup.sh WARNING: You are r

lubuntu踩坑全记录

为了降低系统占用,毕业之后一直用lubuntu不用ubuntu...操作其实差不多,就是lubuntu有一些小坑坑:P 本文是我的踩坑全记录.长期更新. 表现:修改开机程序,改完重启进不了系统了.输入密码后,仍回到登录界面,无法进入系统. 原因:我也不知道,可能系统自己绕死了吧:) 坑:我当前只有一个root用户,没有保存快照,开机看不到GNU GRUB,所以也无法以救援模式进入系统. 解决: 我首先用系统盘片进入了lubuntu安装界面,看help信息 F4说: 这就是让我们自己动手丰衣足食.

Windows Server 2012搭建SQL Server Always On踩坑全记录

Windows Server 2012搭建SQL Server Always On踩坑全记录 环境信息: Windows Server 2012 R2 Sql Server 2012 整个搭建集群的过程主要分为3步: 1.配置预控,并把机器加域. 2.配置windows故障转移集群(Windows Failover Cluster) 3.配置SQL Server Always On High Availability Group(AG) 踩坑全记录 预控配置 比较好配置,需要注意的是非预控机器在