Educational Codeforces Round 55 (Rated for Div. 2)

D. Maximum Diameter Graph

题意

给出每个点的最大度,构造直径尽可能长的树

思路

让度数大于$1$的点构成链,考虑是否能在链的两端加度为$1$的点

代码

#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl;
const int maxn = 1e3+5;
using namespace std;
typedef long long LL;

int n;

struct node{
    int id,val;
}a[maxn];

bool cmp(node a,node b){
    return a.val > b.val;
}
vector<pair<int,int> >vec;

int main(){
    scanf("%d",&n);
    int sum=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i].val);
        sum+=a[i].val;
        a[i].id=i;
    }
    if(sum < (n-1)*2){puts("NO");return 0;}
    sort(a+1,a+1+n,cmp);
    int pos=n,cnt=0;
    for(int i=1;i<=n;i++){
        if(a[i].val > 1)cnt++;
        else{pos=i-1;break;}
    }
    for(int i=2;i<=pos;i++){
        vec.push_back({a[i].id,a[i-1].id});
        a[i].val--;
        a[i-1].val--;
    }
    int ans=pos-1;
    if(pos != n){
        vec.push_back({a[1].id,a[pos+1].id});
        a[1].val--;
        a[pos+1].val--;
        ans++;
    }
    int flag=0;
    for(int j=pos+1;j<=n;j++){
        for(int i=pos;i>=1;i--){
            if(a[j].val == 0)break;
            if(a[i].val == 0)continue;
            vec.push_back({a[j].id,a[i].id});
            a[j].val--;
            a[i].val--;
            if(flag == 0 && i == pos){flag=1;ans++;}
        }
    }
    printf("YES %d\n",ans);
    printf("%d\n",vec.size());
    for(int i=0;i<vec.size();i++){
        printf("%d %d\n",vec[i].first,vec[i].second);
    }
    return 0;
}

E. Increasing Frequency

题意

让某段区间的数字加上某个值使最终等于$c$的数尽可能多

思路

从左往右枚举左边区间最优情况下的情况,考虑与当前左区间右边界相同的值变成c的情况,维护$ans$

代码

#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl;
const int maxn = 5e5+5;
using namespace std;
typedef long long LL;

LL n,k,a[maxn];
LL pre[maxn],suf[maxn],expre[maxn],last[maxn];

int main(){
    scanf("%I64d%I64d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%I64d",&a[i]);
        if(a[i] == k)pre[i]++,suf[i]++;
    }
    for(int i=1;i<=n;i++)pre[i]+=pre[i-1];
    for(int i=n;i>=1;i--)suf[i]+=suf[i+1];
    for(int i=1;i<=n;i++){
        expre[i]=pre[i-1]+1;
        int pos=last[a[i]];
        if(pos)expre[i]=max(expre[i],expre[pos]+1);
        last[a[i]]=i;
    }
    LL ans=0;
    for(int i=1;i<=n+1;i++)ans=max(ans,expre[i-1]+suf[i]);
    printf("%I64d\n",ans);
    return 0;
}

G. Petya and Graph

题意

找到这样的子图满足图内的边只连接图内的点,求最大权值

思路

最大权闭合子图板题,不知道是什么可以看这个博客,bzoj上甚至有原题(这题还不爆int

代码

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL inf  = 1e18;
const LL maxn = 1e5+5;

struct Dinic {
    static const LL maxn = 1e5+5;
    static const LL maxm = 4e5+5;

    struct Edge {
        LL u, v, next, flow, cap;
    } edge[maxm*2];

    LL head[maxn], level[maxn], cur[maxn], eg;

    void addedge(LL u, LL v, LL cap) {
        edge[eg]={u,v,head[u],0,cap},head[u]=eg++;
        edge[eg]={v,u,head[v],0,  0},head[v]=eg++;
    }
    void init() {
        eg = 0;
        memset(head, -1, sizeof head);
    }
    bool makeLevel(LL s, LL t, LL n) {
        for(int i = 0; i < n; i++) level[i] = 0, cur[i] = head[i];
        queue<LL> q; q.push(s);
        level[s] = 1;
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            for(LL i = head[u]; ~i; i = edge[i].next) {
                Edge &e = edge[i];
                if(e.flow < e.cap && level[e.v] == 0) {
                    level[e.v] = level[u] + 1;
                    if(e.v == t) return 1;
                    q.push(e.v);
                }
            }
        }
        return 0;
    }
    LL findpath(LL s, LL t, LL limit = inf) {
        if(s == t || limit == 0) return limit;
        for(LL i = cur[s]; ~i; i = edge[i].next) {
            cur[edge[i].u] = i;
            Edge &e = edge[i], &rev = edge[i^1];
            if(e.flow < e.cap && level[e.v] == level[s] + 1) {
                int flow = findpath(e.v, t, min(limit, e.cap - e.flow));
                if(flow > 0) {
                    e.flow += flow;
                    rev.flow -= flow;
                    return flow;
                }
            }
        }
        return 0;
    }
    LL max_flow(int s, int t, int n) {
        LL ans = 0;
        while(makeLevel(s, t, n)) {
            LL flow;
            while((flow = findpath(s, t)) > 0) ans += flow;
        }
        return ans;
    }
} di;

LL n,m,st,en;
LL a[maxn];

int main() {
    di.init();
    scanf("%I64d%I64d",&n,&m);
    st=0,en=n+m+1;
    for(int i=1;i<=n;i++){
        scanf("%I64d",&a[i]);
        di.addedge(i,en,a[i]);
    }
    LL sum=0;
    for(int i=1;i<=m;i++){
        LL x,y,z;
        scanf("%I64d%I64d%I64d",&x,&y,&z);
        di.addedge(st,i+n,z);
        di.addedge(i+n,x,inf);
        di.addedge(i+n,y,inf);
        sum+=z;
    }
    printf("%I64d\n",sum-di.max_flow(st,en,en+1));
    return 0;
}

  

posted @ 2018-11-29 18:44  WstOne  阅读(141)  评论(0)    收藏  举报