codeforce 1375 DEG

 比赛的时候正在被各种期末课设折磨,结果发病了

/*
每次求mex,如果mex<n,那么让a[mex]=mex,如果mex=n,那么挑a[i]!=i的位置,令a[i]=mex 
这样每安排好一个位置最多进行两次操作 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 5005
#define pb push_back
 
int a[N],n,mex;
vector<int>v;
 
void Mex(){
    int vis[N]={};
    for(int i=0;i<n;i++)vis[a[i]]=1;
    for(int i=0;i<=n;i++)if(!vis[i]){
        mex=i;return;
    }    
}
 
int main(){
    int t;cin>>t;
    while(t--){
        v.clear();cin>>n;
        for(int i=0;i<n;i++)cin>>a[i];
        
        int tot=0;
        while(tot<n){
            int f=0;
            for(int i=0;i<n;i++)if(a[i]!=i)f=1;
            if(!f)break;
            
            Mex();
            if(mex==n){
                for(int i=0;i<n;i++)
                    if(a[i]!=i){
                        a[i]=mex;v.pb(i);
                        break;
                    }
            }else {
                a[mex]=mex;
                v.pb(mex);++tot;
            }
        } 
        cout<<v.size()<<'\n';
        for(auto x:v)cout<<x+1<<' ';
        puts("");
    }
}

E:策略:先把a数组离散化,从n->1逐步将数组变成有序的。对位置i来说,把所有在[1..i-1]的大于a[i]的数找出来,然后一 一交换一次位置,可以既不影响前面的逆序对形式,又把i换到正确的位置上

/*
sort内部好像是随机化过的。。所以如果a[i]==a[j]时记得要判一下i<j,让下标小的排在前面 
*/

#include<bits/stdc++.h>
using namespace std;
#define N 5005
#define pb push_back
#define fi first
#define se second
#define mk make_pair

vector<pair<int,int> >v;
bool mp[N][N];

int n,a[N],id[N],pos[N];
int cmp(int i,int j){
    if(a[i]==a[j])return i<j;
    return a[i]<a[j];
}


int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i],id[i]=i;
    sort(id+1,id+1+n,cmp);
    for(int i=1;i<=n;i++)a[id[i]]=i;
    for(int i=1;i<=n;i++)pos[a[i]]=i;
    
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)if(a[i]>a[j])mp[i][j]=1;
    
    //从后往前固定位置 
    for(int i=n;i>=1;i--){
        int now=a[i];
        for(int j=now;j<i;j++){//所有比now大的数都换一轮位置 
            v.pb(mk(pos[j],pos[j+1])); 
            int x=pos[j],y=pos[j+1];
            swap(pos[j],pos[j+1]);
            swap(a[x],a[y]); 
        }
    }
    
    
    cout<<v.size()<<'\n';
    for(auto p:v){
        if(p.fi>p.se)swap(p.fi,p.se);
        if(mp[p.fi][p.se])
            cout<<p.fi<<" "<<p.se<<'\n';
    }
}

G:可以转换成二分图染色(自己画个大点的样例就很清楚了),然后选数量少的颜色

#include<bits/stdc++.h>
using namespace std;
#define N 400005

vector<int>G[N];
int n,c[N];

void dfs(int u,int pre){
    c[u]=c[pre]^1;
    for(auto v:G[u])
        if(v!=pre)dfs(v,u);
}

int main(){
    cin>>n;
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,1);
    int c1=0,c0=0;
    for(int i=1;i<=n;i++)
        if(c[i]==0)c0++;
        else c1++;
    cout<<min(c0,c1)-1<<'\n';
} 

 

posted on 2020-07-09 18:57  zsben  阅读(101)  评论(0编辑  收藏  举报

导航