• 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的最短路和

    扫描一下联通块

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

  • 相关阅读:
    想不赚钱都难的7大行业
    [转帖]一位年轻商人的经验感悟
    对待下级十二条准则
    让自己幸福的10条秘诀
    孤独感
    “3+3”看华为云FusionInsight如何引领“数据新基建”持续发展
    【乘风破浪的开发者】丁一超:从AI实战营出发探索未知的AI世界
    适用初学者的5种Python数据输入技术
    遥感影像处理有高招,“专治”各类花式并发的述求!
    从“小众”到“首选”,推动云原生产业落地华为云作用几何?
  • 原文地址:https://www.cnblogs.com/chouti/p/5785190.html
Copyright © 2020-2023  润新知