百度之星 初赛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;
}

猜你喜欢

转载自blog.csdn.net/qq_37774171/article/details/81626511
今日推荐