zoukankan      html  css  js  c++  java
  • 20160818训练记录

    T1

    image

    “开心题”

    每个点如果不是根节点,子树个数等于度数减一。然后随便算一算

    T2

    image

    数据范围

    image

    首先对于两个长度相等的偶数串。把他两两分组

    1 2 3 4
    5 6 7 8

    考虑一个和8相等的(包括交换内部后)的块

    先把他调到头部然后调到尾部。然后删除这一块

    然后发现这样的可以对每个串求出字典序最小的等价表达。。其实随便计算一下就解决了

    #include<cstdio>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,sc[55],len[55],ls[55][66],_ls[55];
    char mz[55][66];
    bool same(pair<char,char>p[],int b){
        pair<char,char >pb[55];int _p=0;
        for(int j=1;j<=len[b]/2;j++){
            if(mz[b][(j<<1)-1]>mz[b][j<<1])
                pb[++_p]=make_pair(mz[b][(j<<1)],mz[b][(j<<1)-1]);
            else pb[++_p]=make_pair(mz[b][(j<<1)-1],mz[b][(j<<1)]);
        }
        sort(pb+1,pb+_p+1);
        for(int i=1;i<=_p;i++){
            if(p[i]!=pb[i]){
                return false;
            }    
        }return true;
    }
    int main(){
        freopen("list.in","r",stdin);
        freopen("list.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",mz[i]+1);len[i]=strlen(mz[i]+1);
        }
        for(int i=1;i<=n;i++){
            if(!sc[i]){
                for(int j=1;j<=len[i]/2;j++){
                    if(mz[i][(j<<1)-1]>mz[i][j<<1])
                        p[++_p]=make_pair(mz[i][(j<<1)],mz[i][(j<<1)-1]);
                    else p[++_p]=make_pair(mz[i][(j<<1)-1],mz[i][(j<<1)]);
                } 
                sort(p+1,p+_p+1);
                for(int j=1;j<=n;j++){
                    if(len[i]!=len[j]||(len[i]&1)!=(len[j]&1))continue;
                    if((len[i]&1)&&(len[j]&1)){
                        if(mz[i][len[i]]!=mz[i][len[j]])continue;
                    }
                    if(same(p,j)){
                        sc[i]=sc[j]=true; ls[i][++_ls[i]]=j;
                    }
            
                }
            }
        }
        int ans=0;
    
        for(int i=1;i<=n;i++){
            ans+=(_ls[i]&1);
        }
        cout<<ans;
        return 0;
    }

    T3

    对于一个图。给定固定点对,求删边一条边后点对的最短路

    20%暴力

    //segment tree beats!
    //I can program a segment but tree,not for this problem
    #include<queue>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    
    ll inf =1000000000ll*1000000000ll;
    struct edge{
        int to,next,v;
    }e[400005];
    int n,m,q,_s,_t,du,dv,last[210000],cnt,inq[200001];
    ll dis[200001];
    void insert_directed(int a,int b,int c){e[++cnt]=(edge){b,last[a],c};last[a]=cnt;}
    void link(int a,int b,int c){insert_directed(a,b,c);insert_directed(b,a,c);}
    int gg;
    ll spfa(int s,int t){
        queue<int>q;
        for(int i=1;i<=n;i++)dis[i]=1000000000ll*1000000000ll,inq[i]=false;
        q.push(s);dis[s]=0;inq[s]=true;
        while(!q.empty()){
            int c=q.front();q.pop();inq[c]=false;
            for(int i=last[c];i;i=e[i].next){    
                int x=e[i].to;
                if(c==du&&x==dv)continue;
                if(c==dv&&x==du)continue;
                    
                    if(dis[c]+e[i].v<dis[x]){
                        dis[x]=dis[c]+e[i].v;
                        if(!inq[x]){
                            q.push(x);inq[x]=true;
                        }
                    }
                
            }
        }
        return dis[t];
    }
    namespace luangao{
        int pre[200001];
        ll spfa(int s,int t){
            queue<int>q;
            for(int i=1;i<=n;i++)dis[i]=1000000000ll*1000000000ll,inq[i]=false;
            q.push(s);dis[s]=0;inq[s]=true;
            while(!q.empty()){
                int c=q.front();q.pop();inq[c]=false;
                for(int i=last[c];i;i=e[i].next){    
                    int x=e[i].to;
                    if(c==du&&x==dv)continue;
                    if(c==dv&&x==du)continue;
                        
                        if(dis[c]+e[i].v<dis[x]){
                            pre[x]=c;
                            dis[x]=dis[c]+e[i].v;
                            if(!inq[x]){
                                q.push(x);inq[x]=true;
                            }
                        }
                    
                }
            }
            return dis[t];
        }
        ll hs(int a,int b){
            return a*200001+b;
        }
        ll H[200001];int _H=0;
        bool find(ll x){
            int l=1,r=_H,mid;
            while(l<=r){
                //if(x==hs(1,2))cout<<l <<' '<<r<<endl;
                mid=(l+r)/2;
                if(x==H[mid])return true;
                if(x>H[mid])l=mid+1;
                else r=mid-1;
            }
            return x==H[mid];
        }
        int main(){
            ll sssp=spfa(_s,_t);
            int t=_t;
            while(pre[t]){
                H[++_H]=hs(pre[t],t);
                H[++_H]=hs(t,pre[t]);
                t=pre[t];
            }
            sort(H+1,H+_H+1);
            //for(int i=1;i<=_H;i++)cout<<H[i]<<endl; 
            //cout<<hs(1,2)<<endl;
            for(int i=1;i<=q;i++){
                scanf("%d %d",&du,&dv);
                ll x=hs(du,dv);
                //cout<<find(x)<<':';
                ll ans;
                if(find(x))ans=spfa(_s,_t);
                else ans=sssp;
                if(ans>=inf)puts("Infinity");
                else printf("%I64d
    ",ans);
            }
            return 0;
        }
    }
    int main(){
        freopen("dream.in","r",stdin);
        freopen("dream.out","w",stdout);
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v,va;
            scanf("%d %d %d",&u,&v,&va);link(u,v,va);
        }
        scanf("%d %d %d" ,&_s,&_t,&q);
        if(n<=4000&&m<=4000)
            for(int i=1;i<=q;i++){
                scanf("%d %d",&du,&dv);
                ll ans=spfa(_s,_t);
                if(ans>=inf)puts("Infinity");
                else printf("%I64d
    ",ans);
            }
        else luangao::main();
    }

    正解

    两种做法

    一种线段树的。http://tonyfang.is-programmer.com/posts/205232.html

    OrzFang%%%

    第二种堆的做法==

    考虑一个最短路图的情况。最短路图是每一条边都在最短路上的边

    那么影响答案的肯定是割边被删除

    那么我们考虑s-t中的联通块依序处理。如果是这之间的割边答案会变成这个和后面所有的联通块之间连边最小值与两端到s、t的最短路和

    扫描一下联通块

    这样每条边都会进堆出堆一次 复杂度得到保证

  • 相关阅读:
    NLP概览(一)
    java正则表达式实例
    notepad++
    Mybatis点滴
    (转)GNU Make学习总结(二)
    (转)GNU Make学习总结(一)
    分页查询
    第三方插件
    单例模式读取数据库配置文件和JNDI连接数据源
    过滤器与监听器
  • 原文地址:https://www.cnblogs.com/chouti/p/5785190.html
Copyright © 2011-2022 走看看