返回顶部

AtCoder Beginner Contest 218 (A~F)

A - Weather Forecast

水题

B - qwerty

水题

C - Shapes

不想写模拟,555

D - Rectangles

题意 :二位坐标轴上有\(n\)个点,问你能构造多少和坐标轴平行的矩形.

题解:暴力枚举左上和右下,用map存一下每个点是否出现。

代码

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

int n;
PII pt[N];
map<PII,int> mp;

int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d %d",&pt[i].fi,&pt[i].se);
        mp[{pt[i].fi,pt[i].se}]++;
    }
    ll ans=0;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            if(pt[i].fi>=pt[j].fi || pt[i].se<=pt[j].se) continue;
            int x1=pt[i].fi,y1=pt[j].se,x2=pt[j].fi,y2=pt[i].se;
            if(mp[{x1,y1}] && mp[{x2,y2}]) ans++;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

E - Destruction

题意\(m\)条边,\(n\)个顶点的图,每条边都有边权,删去一条边可以得到这条边边权的贡献,问你在保证图是连通的情况下,能得到的最大贡献是多少。

题解:先用最小生成树把最小的边用来保证连通,剩下的边如果大于0就记录给答案即可。

代码

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

int n,m;
struct Node{
    int a,b;
    int val;
}edge[N];
int p[N];

int find(int x){
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

int main() {
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;++i){
        scanf("%d %d %d",&edge[i].a,&edge[i].b,&edge[i].val);
    }
    sort(edge+1,edge+1+m,[&](Node x,Node y){
        return x.val<y.val;
    });
    for(int i=1;i<=n;++i) p[i]=i;
    ll res=0;
    vector<int> v;
    ll tmp=0;
    for(int i=1;i<=m;++i){
        int fa=find(edge[i].a);
        int fb=find(edge[i].b);
        int val=edge[i].val;
        if(fa!=fb){
            p[fa]=fb;
            res+=val;
        }
        else v.pb(val);
    }
    for(auto w:v){
        if(w>0) tmp+=w;
    }
    printf("%lld\n",tmp);
    return 0;
}

F - Blocked Roads

题意:给你一张\(n\)个点\(m\)条边的有向图,所有边权为\(1\),每次删去一条边,问从\(1\)\(n\)的最短距离。

题解:如果每次删去一条边直接暴力跑,复杂度为\(O(M*(N+M))\),但是我们先找到一条最短距离的简单路径,容易知:这条最短路径最多有\(n-1\)条边,所以,删去这条最短路径之外的边,最短距离不发生变化,那么现在就要考虑删去最短路径的边怎么办,怎么办?暴力呗,此时的复杂度被优化到\(O(N*(N+M))\).完全满足条件。

代码

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

int n,m;
vector<int> edge[N];
int dis[N];
map<PII,int> rec,mp;
int ans[N];
vector<PII> v[N];

int main() {
    me(dis,-1,sizeof(dis));
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;++i){
        int u,v;
        scanf("%d %d",&u,&v);
        edge[u].pb(v);
        rec[{u,v}]=i;
    }
    queue<int> q;
    q.push(1);
    dis[1]=0;
    vector<PII> path;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(auto w:edge[u]){
            if(dis[w]==-1){
                dis[w]=dis[u]+1;
                q.push(w);
                v[w].pb({u,w});
            } 
        }
    }
    if(dis[n]==-1){
        for(int i=1;i<=m;++i) printf("-1\n");
        return 0;
    }
    int cur=n;
    while(cur!=1){
        path.pb({v[cur][0].fi,v[cur][0].se});
        cur=v[cur][0].fi;
    }
    for(int i=1;i<=m;++i) ans[i]=dis[n];
    for(auto w:path){
        mp[{w.fi,w.se}]=1;
        for(int i=1;i<=n;++i) dis[i]=-1;
        while(!q.empty()) q.pop();
        q.push(1);
        dis[1]=0;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(auto w:edge[u]){
                if(mp[{u,w}]==1) continue;
                if(dis[w]==-1){
                    dis[w]=dis[u]+1;
                    q.push(w);
                }
            }
        }
        ans[rec[{w.fi,w.se}]]=dis[n];
        mp[{w.fi,w.se}]=2;
    }
    for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
    return 0;
}

posted @ 2021-09-11 22:03  Rayotaku  阅读(86)  评论(0编辑  收藏  举报