码迷,mamicode.com
首页 > 其他好文 > 详细

CCPC-Wannafly Summer Camp 2019 全记录

时间:2019-07-31 10:51:14      阅读:561      评论:0      收藏:0      [点我收藏+]

标签:scanf   strong   summer   注意   不用   type   连通   i++   back   

 // 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;
}
View Code

 

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;
}
View Code

 

 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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

 

Day2

Day3

Day4

Day5

Day6

 

CCPC-Wannafly Summer Camp 2019 全记录

标签:scanf   strong   summer   注意   不用   type   连通   i++   back   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!