some problem

CF1239D Catowice City

$solution:$

考虑类似于 $2-SAT$ 将必须选择的关系连边,$tarjan$ 后让最开始遍历的强连通分量为 $1$ ,因为 $dfs$ 的顺序易知这是正确的。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=1000001;
int n,m,T,col[MAXN],sta[MAXN],num,dfn[MAXN],low[MAXN],Ans0[MAXN],Ans1[MAXN];
vector<int> vec[MAXN];
void Init(){
    num=0;Ans0[0]=0,Ans1[0]=0;
    for(int i=0;i<=n;i++) vec[i].clear();
    for(int i=0;i<=n;i++) col[i]=dfn[i]=low[i]=0;
}
void tarjan(int u){
    dfn[u]=low[u]=++num;sta[++sta[0]]=u;
    int siz=vec[u].size();
    for(int i=0;i<siz;i++){
        int v=vec[u][i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(!col[v]) low[u]=min(low[u],low[v]);
    }
    if(dfn[u]==low[u]){
        col[u]=++col[0];
        while(sta[sta[0]]!=u){
            col[sta[sta[0]]]=col[0];
            sta[0]--;
        }sta[0]--;
    }return;
}
int main(){
//    freopen("8.in","r",stdin);
    T=read();
    while(T--){
        n=read(),m=read();
        Init();
        for(int i=1;i<=m;i++){int u=read(),v=read();vec[u].push_back(v);}
        for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
        if(col[0]==1){printf("No\n");continue;}
        for(int i=1;i<=n;i++){
            if(col[i]==1) Ans0[++Ans0[0]]=i;
            else Ans1[++Ans1[0]]=i;
        }
        printf("Yes\n%d %d\n",Ans0[0],Ans1[0]);
        for(int i=1;i<=Ans0[0];i++) printf("%d ",Ans0[i]);printf("\n");
        for(int i=1;i<=Ans1[0];i++) printf("%d ",Ans1[i]);printf("\n");
    }return 0;
}
View Code

CF1244F Chips

$solution:$

考虑若对于 $i$ 来说在 $i-1,i+1$ 有颜色相同的话,那么无论经过多少次操作都可以为本身颜色。

否则,与其相邻的是 $01$ 段,模拟一下即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=4000001;
char str[MAXN];
int n,k,A[MAXN],B[MAXN],C[MAXN];
void print(int opt){opt?printf("W"):printf("B");}
int main(){
    n=read(),k=read();
    scanf("%s",str+1);
    for(int i=1;i<=n;i++) A[i]=(str[i]=='W');
    A[0]=A[n],A[n+1]=A[1];
    for(int i=1;i<=n;i++) B[i]=(A[i-1]==A[i]||A[i]==A[i+1]),B[i+n]=B[i];
    bool F=0;for(int i=1;i<=n;i++) F|=B[i];
    if(!F){for(int i=1;i<=n;i++) print(A[i]^(k&1));printf("\n");return 0;}
    int ps=1;for(int i=1;i<=n;i++) if(B[i]) ps=i;
    for(int i=n+1;i<=2*n;i++){if(B[i]) ps=i;C[i-n]=i-ps;}
    for(int i=2*n;i>n;i--) if(B[i]) ps=i;
    for(int i=n;i>=1;i--){if(B[i]) ps=i;C[i]=min(C[i],ps-i);}
    for(int i=1;i<=n;i++){
        if(B[i]) print(A[i]);
        else print(A[i]^(min(k,C[i])&1));
    }printf("\n");return 0;
}
View Code

CF1245F Daniel and Spring Cleaning

$solution:$

按维容斥后做简单数位 $dp$ 即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=30;
int T,a,b,A[MAXN],B[MAXN],len,f[MAXN][2][2];
int dfs(int ps,int lim1,int lim2){
    if(ps==-1) return 1;
    if(f[ps][lim1][lim2]!=-1) return f[ps][lim1][lim2];
    int e1=(lim1==1)?A[ps]:1,e2=(lim2==1)?B[ps]:1,res=0;
    for(int i=0;i<=e1;i++)
        for(int j=0;j<=e2;j++){
            if(i==1&&j==1) continue;
            res+=dfs(ps-1,lim1&&(i==A[ps]),lim2&&(j==B[ps]));
    }
    return f[ps][lim1][lim2]=res;
}    
int calc(int x,int y){
    if(x<0||y<0) return 0;
    memset(f,-1,sizeof(f));
    len=29;
    for(int i=29;i>=0;i--) A[i]=(x&(1<<i))?1:0;
    for(int i=29;i>=0;i--) B[i]=(y&(1<<i))?1:0;
    return dfs(29,1,1);
} 
signed main(){
//    freopen("4.in","r",stdin);
    T=read();
    while(T--){
        int l=read(),r=read();
        printf("%lld\n",calc(r,r)+calc(l-1,l-1)-2*calc(l-1,r));
    }
    return 0;
}
View Code

CF1245E Hyakugoku and Ladders

 $solution:$

设 $f_{i,j}$ 表示从 $(i,j)$ 走到 $(1,1)$ 的期望步数,按题意模拟的转移即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int N=11;
int M[N][N],fro[N*N]; 
double f[N*N];
int main(){
    for(int i=1;i<=10;i++)
        for(int j=1;j<=10;j++){
            if(i&1) M[i][j]=(i-1)*10+j;
            else M[i][j]=(i-1)*10+11-j;
        }
    double sum=0;
    f[1]=0;for(int i=2;i<=6;i++){
        f[i]=(sum+6)/(i-1);
        sum+=f[i];
    }
    for(int i=1;i<=10;i++){
        for(int j=1;j<=10;j++){int x=read();fro[M[i][j]]=M[i-x][j];}
    }
    for(int i=7;i<=100;i++){
        double s=0;
        for(int j=1;j<=6;j++) s+=min(f[i-j],f[fro[i-j]]);
        f[i]=s/6.0+1;
    }
    printf("%.10lf\n",f[100]);return 0;
}
View Code

CF1249F Maximum Weight Subset

$solution:$

设 $f_{i,j}$ 表示以 $i$ 号节点为根的子树下距离 $i$ 最近的点至少为 $j$ 的方案数,枚举哪个要选即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int N=211; 
int n,k,f[N][N],head[N],cnt,val[N],son[N];
struct node{
    int u,v,nex;
}x[N<<1];
void add(int u,int v){
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int u,int fath){
    for(int i=head[u];i!=-1;i=x[i].nex){
        if(x[i].v==fath) continue;
        dfs(x[i].v,u);
    }
    son[0]=0;
    for(int i=head[u];i!=-1;i=x[i].nex){
        if(x[i].v==fath) continue;
        son[++son[0]]=x[i].v;
    }
    for(int i=0;i<=k;i++){
        if(i==0){
            f[u][0]=val[u];
            for(int j=1;j<=son[0];j++) f[u][0]+=f[son[j]][k];
            continue;
        }
        for(int j=1;j<=son[0];j++){
            int res=f[son[j]][i-1]; 
            for(int p=1;p<=son[0];p++){
                if(j==p) continue;
                res+=f[son[p]][max(k-i,i-1)];
            }
            f[u][i]=max(f[u][i],res);
        }
    }for(int i=k;i>=0;i--) f[u][i]=max(f[u][i],f[u][i+1]);
}
int main(){
    memset(head,-1,sizeof(head));
    n=read(),k=read();
    for(int i=1;i<=n;i++) val[i]=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        add(u,v),add(v,u);
    }dfs(1,0);
    printf("%d\n",f[1][0]);return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/si-rui-yang/p/11794120.html