百度之星 初赛B

A :传送门:点我

求联通块个数,对于简单图而言,就是c=v-e,其中c就是联通块个数,v是顶点数,e是边数

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
const int MAX_N = 2e5 + 10;
int N, M, K;

vector<int> G[MAX_N];
int vis[MAX_N];
int degree[MAX_N];

void dfs(int v, int p) {
    vis[v] = 1;
    for (int i = 0; i < G[v].size(); i++) {
        int u = G[v][i];
        if (!vis[u] && u != p)
            dfs(u, v);
    }
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d %d %d", &N, &M, &K);
        for (int i = 0; i < N; i++) {
            G[i].clear();
            vis[i] = 0;
            degree[i] = 0;
        }

        int a, b;
        for (int i = 0; i < M; i++) {
            scanf("%d %d", &a, &b);
            G[a].push_back(b);
            G[b].push_back(a);
            degree[a]++;
            degree[b]++;
        }

        int cnt = 0;
        for (int i = 0; i < N; i++)
            if (!vis[i]) {
                cnt++;
                dfs(i, -1);
            }
        int ans = 0;
        for (int i = 0; i < N; i++) {
            int tmp = N - degree[i] - 1;
            int t = min(tmp, cnt - 1 + K);
            ans = max(ans, degree[i] + t);
        }
        printf("%d\n", ans);
    }
    return 0;
}

D p1m2 传送门:点我

二分答案,会超时,加一个前缀

#include <algorithm>
#include <cstdio>
using namespace std;
const int MAX_N = 3e5 + 10;
typedef long long ll;
int X[MAX_N];
int N;
ll sum[MAX_N];
bool cmp(int a,int b){
    return a>b;
}

int check(int x){
    int i;
    ll cnt=0;
    for (i = 1; i <= N; i++){
        if (X[i] > x)
            cnt += (X[i]-x)/2;  //减的次数 
        else 
            break;
       /* if (X[i] > x) {
            int t = (X[i] - x) / 2;
            cnt -= t;
        }*/
    }
    cnt=cnt-((ll)(N-i+1)*x-sum[i]);
    if(cnt>0){
        return 1;
    }
    else if(cnt==0){
        return 0;
    }
    else return -1;
}
int main(){
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &N);
        int l = 1e8, r = 0;
        for (int i = 1; i <= N; i++){
            scanf("%d", &X[i]);
            l=min(l,X[i]);r=max(r,X[i]);
        }
        sort(X+1,X+N+1,cmp);//求一个后缀和 
        sum[N]=X[N];
        for(int i=N-1;i>=1;i--){
            
            sum[i]=sum[i+1]+X[i]; 
        }
        int ans=-1;
        while (l  <= r) {
            int mid = l + r >> 1;
            int j = check(mid);
            if (j >= 0){
                ans=mid;
                l = mid+1;
            }
                
            else
                r = mid-1;
        }
        printf("%d\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值