Codeforces IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2)

C. Bear and Up-Down

当不满足要求的数超过4个的时候,肯定是无解的,否则用每个数和这4个数交换,然后check。。比赛的时候写了很繁琐的分类讨论,竟然没挂。。

#include <bits/stdc++.h>
#include <unordered_map>

#define ll long long 

using namespace std;


int a[150010];

int err[150010];
int n;

bool judge(){
    for(int i=1;i<n;i++){
        if(i&1){
            if(a[i]>=a[i+1]){
                return 0;
            }
        }else{
            if(a[i]<=a[i+1]){
                return 0;
            }
        }
    }
    return 1;
}

int main(){

    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }

    int cnt= 0;

    for(int i=1;i<n;i++){
        if(i&1){
            if(a[i]>=a[i+1]){
                err[cnt++] = i;
            }
        }else{
            if(a[i]<=a[i+1]){
                err[cnt++] = i;
            }
        }
    }
    int ans = 0;

    if(cnt>4){

    }else if(cnt==4){
        if(err[0]+1==err[1] && err[2]+1==err[3]){
            swap(a[err[1]],a[err[3]]);
            ans+=judge();
            swap(a[err[1]],a[err[3]]);

        }else{

        }
    }else if(cnt==3){
        if(err[0]+2==err[2]){
            swap(a[err[1]],a[err[2]]);
            ans+=judge();
            swap(a[err[1]],a[err[2]]);

            swap(a[err[1]],a[err[2]+1]);
            ans+=judge();
            swap(a[err[1]],a[err[2]+1]);

            swap(a[err[0]],a[err[2]]);
            ans+=judge();
            swap(a[err[0]],a[err[2]]);
        }if(err[0]+1==err[1]){
            swap(a[err[1]],a[err[2]]);
            ans+=judge();
            swap(a[err[1]],a[err[2]]);

            swap(a[err[1]],a[err[2]+1]);
            ans+=judge();
            swap(a[err[1]],a[err[2]+1]);

        }else if(err[1]+1==err[2]){
            swap(a[err[0]],a[err[2]]);
            ans+=judge();
            swap(a[err[0]],a[err[2]]);

            swap(a[err[0]+1],a[err[2]]);
            ans+=judge();
            swap(a[err[0]+1],a[err[2]]);

        }else{

        }
    }else if(cnt==2){
        if(err[0]+1==err[1]){
            swap(a[err[0]],a[err[1]+1]);
            ans+=judge();
            swap(a[err[0]],a[err[1]+1]);

            for(int i=1;i<=n;i++){
                swap(a[i],a[err[1]]);

                bool ok = 1;
                for(int j=i-3;j<=i+3;j++){
                    if(j<1)continue;
                    if(j>=n)continue;
                    if(j&1){
                        if(a[j]>=a[j+1]){
                            ok = 0;
                        }
                    }else{
                        if(a[j]<=a[j+1]){
                            ok = 0;
                        }
                    }
                }

                for(int j=err[1]-3;j<=err[1]+3;j++){
                    if(j<1)continue;
                    if(j>=n)continue;
                    if(j&1){
                        if(a[j]>=a[j+1]){
                            ok = 0;
                        }
                    }else{
                        if(a[j]<=a[j+1]){
                            ok = 0;
                        }
                    }
                }

                swap(a[i],a[err[1]]);
                ans+=ok;
            }

        }else{
            swap(a[err[0]],a[err[1]]);
            ans+=judge();
            swap(a[err[0]],a[err[1]]);

            swap(a[err[0]],a[err[1]+1]);
            ans+=judge();
            swap(a[err[0]],a[err[1]+1]);

            swap(a[err[0]+1],a[err[1]]);
            ans+=judge();
            swap(a[err[0]+1],a[err[1]]);

            swap(a[err[0]+1],a[err[1]+1]);
            ans+=judge();
            swap(a[err[0]+1],a[err[1]+1]);
        }
    }else if(cnt==1){
        for(int i=1;i<=n;i++){
            swap(a[i],a[err[0]]);

            bool ok = 1;
            for(int j=i-3;j<=i+3;j++){
                if(j<1)continue;
                if(j>=n)continue;
                if(j&1){
                    if(a[j]>=a[j+1]){
                        ok = 0;
                    }
                }else{
                    if(a[j]<=a[j+1]){
                        ok = 0;
                    }
                }
            }

            for(int j=err[0]-3;j<=err[0]+3;j++){
                if(j<1)continue;
                if(j>=n)continue;
                if(j&1){
                    if(a[j]>=a[j+1]){
                        ok = 0;
                    }
                }else{
                    if(a[j]<=a[j+1]){
                        ok = 0;
                    }
                }
            }

            swap(a[i],a[err[0]]);
            ans+=ok;
        }

        for(int i=1;i<=n;i++){
            if(i==err[0])continue;
            swap(a[i],a[err[0]+1]);

            bool ok = 1;
            for(int j=i-3;j<=i+3;j++){
                if(j<1)continue;
                if(j>=n)continue;
                if(j&1){
                    if(a[j]>=a[j+1]){
                        ok = 0;
                    }
                }else{
                    if(a[j]<=a[j+1]){
                        ok = 0;
                    }
                }
            }

            for(int j=err[0]-3;j<=err[0]+3;j++){
                if(j<1)continue;
                if(j>=n)continue;
                if(j&1){
                    if(a[j]>=a[j+1]){
                        ok = 0;
                    }
                }else{
                    if(a[j]<=a[j+1]){
                        ok = 0;
                    }
                }
            }

            swap(a[i],a[err[0]+1]);
            ans+=ok;
        }
    }

    cout<<ans<<endl;
    return 0;
}

D. Delivery Bears

这是一道好题!解法是二分答案,然后跑最大流判是否可行。判断方法是将边的流量改为它除以答案的值,向下取整,如果最大流不小于x就是合法。
另外要注意,二分写成循环固定次数会比较好。

#include <bits/stdc++.h>
#include <unordered_map>

#define ll long long 
using namespace std;

int n,m;
double x;

const int inf=0xfffff;  
const int N = 55;  
int  pre[N];

double maxflow,dp[N][N];

double tmp[N][N];

void Edmonds_Karp(int start, int end, int m){  
    while(1){  
        queue<int> p;  
        double minflow = inf;  
        p.push(1);
        memset(pre, 0, sizeof(pre));
        while(!p.empty()){
            int u = p.front();  
            p.pop();  
            if(u == end)               
                break;  
            for(int i = 1;i <= m;i++)  
                if(dp[u][i] > 0&&pre[i] == 0){   
                    pre[i] = u;                
                    p.push(i);  
                }      
        }  
        if(pre[end] == 0)  
            break;  
        for(int i = end;i != start;i = pre[i])  
            minflow = min(minflow, dp[pre[i]][i]);  
        for(int i = end;i != start;i = pre[i])  {  
            dp[pre[i]][i] -= minflow; 
            dp[i][pre[i]] += minflow;  
        }  
        maxflow+=minflow;  
    }  
} 


int main(){
    cin>>n>>m>>x;
    for(int i=1;i<=m;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        dp[a][b]+=c;
    }
    memcpy(tmp,dp,sizeof(dp));

    double l=0;
    double r=1000000;
    double mid = 0;
    //注意这个二分的姿势 
    for(int tt=0;tt<66;tt++){
        mid = (l+r)/2;
        memcpy(dp,tmp,sizeof(dp));
        for(int i=0;i<=n;i++){
            for(int j=0;j<=n;j++){
                dp[i][j] = floor(dp[i][j]/mid);
            }
        }
        maxflow = 0;
        Edmonds_Karp(1,n,n);

        if(maxflow>=x){
            l=mid;
        }else{
            r=mid;
        }
    }

    printf("%.10f\n",mid*x);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值