码迷,mamicode.com
首页 > 其他好文 > 详细

日常练习1

时间:2017-09-05 13:27:38      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:fine   也有   连接   判断   als   一个   div   log   技术分享   

T1

技术分享

—————————————————————————————————————————————

这道题我是用树形dpA的 $f[i][j]$ 表示包含点i在内的他的子树 内一共有j(j=0或1)个不合法点

x表示当前点 now表示他的某一个儿子

 $f[x][1]=min(f[x][1]+f[now][0],f[x][0]+f[now][1],f[x][1]+f[now][1]+e[i].w)$

 $f[x][0]=min(f[x][0]+f[now][1],f[x][0]+f[now][0]);$

然后就瞎搞一下就可以A了 注意初始化 不合法点x的$f[x][0]=inf$ 这样才能保证准确性

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using std::min;
const int M=1e5+7;
const LL inf=1e18;
int read(){
    int ans=0,f=1,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 ans*f;
}
int n,k,vis[M];
LL f[M][2];
int first[M],cnt;
struct node{int to,next,w;}e[2*M];
void ins(int a,int b,int w){e[++cnt]=(node){b,first[a],w}; first[a]=cnt;}
void insert(int a,int b,int w){ins(a,b,w); ins(b,a,w);}
void dfs(int x){
    vis[x]=1;
    for(int i=first[x];i;i=e[i].next){
        int now=e[i].to;
        if(vis[now]) continue;
        dfs(now);
        f[x][1]=min(f[x][0]+f[now][1],f[x][1]+min(f[now][0],f[now][1]+e[i].w));
        f[x][0]=f[x][0]+min(f[now][1]+e[i].w,f[now][0]);
    }
}
int main(){
    int x,y,w;
    n=read(); k=read(); 
    for(int i=1;i<=k;i++) x=read(),f[x][0]=inf;
    for(int i=1;i<n;i++) x=read(),y=read(),w=read(),insert(x,y,w);
    dfs(1);
    printf("%lld\n",min(f[1][0],f[1][1]));
    return 0;
}
View Code

当然也有并查集的写法 就是按边从大到小排序然后如果这条边连接的两个并查集的话

就删掉这条变 删掉边的总和就是答案了

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using std::min;
const int M=1e5+7;
const LL inf=1e18;
int read(){
    int ans=0,f=1,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 ans*f;
}
LL ans;
int cnt,n,k,f[M],h[M];
int find(int x){while(f[x]!=x) x=f[x]=f[f[x]]; return x;}
struct node{int from,to,w;}e[2*M];
bool cmp(node a,node b){return a.w>b.w;}
int main(){
    int x,y,w;
    n=read(); k=read(); 
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=k;i++) x=read(),h[x]=1;
    for(int i=1;i<n;i++) x=read(),y=read(),w=read(),e[++cnt]=(node){x,y,w};
    std::sort(e+1,e+1+n,cmp);
    for(int i=n;i;i--){
        int p=find(e[i].from),q=find(e[i].to);
        if(h[p]&&h[q]) ans+=e[i].w;
        else f[q]=p,h[p]+=q;
    }printf("%lld\n",ans);
    return 0;
}
View Code

T2

技术分享

————————————————————————————————————————

这道题我写的是O(n)的hash判相等 枚举长度判断相等就吼了

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
const int M=2e5+7,P=9875321;
unsigned long long h1[M],h2[M],w[M];
int read(){
    int ans=0,f=1,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 ans*f;
}
char c[26],s1[M],s2[M];
int cnt,ans,wh[26];
bool f=false;
int main(){
    scanf("%s",c);
    for(int i=0;i<26;i++) wh[c[i]-a]=i;
    scanf("%s",s1+1); cnt=strlen(s1+1);
    for(int i=1;i<=cnt;i++) s2[i]=c[s1[i]-a];
    w[0]=1; for(int i=1;i<=cnt;i++) w[i]=w[i-1]*P;
    for(int i=1;i<=cnt;i++) h1[i]=h1[i-1]*P+s1[i];
    for(int i=1;i<=cnt;i++) h2[i]=h2[i-1]*P+s2[i];
    for(int d=cnt/2;d;d--){
        if(h1[d]==h2[cnt]-h2[cnt-d]*w[d]){f=true; ans=d; break;}
    }
    if(!f){
        printf("%s",(s1+1));
        for(int i=1;i<=cnt;i++) printf("%c",a+wh[s1[i]-a]);
    }
    else{
        for(int i=1;i<=cnt-ans;i++) printf("%c",s1[i]);
        for(int i=1;i<=cnt-ans;i++) printf("%c",a+wh[s1[i]-a]);
        printf("\n");
    }
    return 0;
}
View Code

技术分享

——————————————————————————————————

这道题就是类似插头dp的东西 要分一堆类 枚举一个2x2的矩形四条条边的选与不选

一共16(2^4) 种情况 然后就看一下怎么转移 $f[i][j][k]$表示前i行选了j个联通块 当前行中间是否有横杠

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
const int M=2e3+9,mod=1e8+7;
int read(){
    int ans=0,f=1,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 ans*f;
}
int n,m;
LL f[M][M][2];
int main(){
    n=read(); m=read();
    f[1][1][0]=1; f[1][2][1]=1;
    for(int i=2;i<=n;i++){
//        int(*now)[2]=f[i-1];
        LL(&last)[M][2]=f[i-1];
        for(int k=1;k<=m;k++){
            f[i][k][0]=(last[k][0]+2*last[k][1]+last[k-1][0]+last[k-1][1])%mod;
            f[i][k][1]=(last[k-1][0]*2+last[k][1]+2*last[k-1][1]+last[k-2][0]+last[k-2][1])%mod;
        }
    }printf("%lld\n",(f[n][m][0]+f[n][m][1])%mod);
    return 0;
}
View Code

 

日常练习1

标签:fine   也有   连接   判断   als   一个   div   log   技术分享   

原文地址:http://www.cnblogs.com/lyzuikeai/p/7477203.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!