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

    扫描一下联通块

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

  • 相关阅读:
    Codeforces Round#410 Div.2
    AtCoder Beginner Contest-060
    如何将gedit变成c++编译器
    洛谷 P2486 [SDOI2011]染色
    让lu哥头痛了许久的代码(洛谷:树的统计)
    字符串模拟入门
    luogu P1553 数字反转(升级版)
    那些令人难忘的——坑
    luogu P1341 无序字母对
    最短路相关题目
  • 原文地址:https://www.cnblogs.com/chouti/p/5785190.html
Copyright © 2020-2023  润新知