zoukankan      html  css  js  c++  java
  • 模板合集

    洛谷P3371【模板】单源最短路径

    题目描述

    如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

    输入输出格式

    输入格式:

    第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。

    接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。

    输出格式:

    一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)

    输入输出样例

    输入样例#1: 复制
    4 6 1
    1 2 2
    2 3 2
    2 4 1
    1 3 5
    3 4 3
    1 4 4
    输出样例#1: 复制
    0 2 4 3

    说明

    时空限制:1000ms,128M

    数据规模:

    对于20%的数据:N<=5,M<=15

    对于40%的数据:N<=100,M<=10000

    对于70%的数据:N<=1000,M<=100000

    对于100%的数据:N<=10000,M<=500000

    不多说,复习一下代码。

      spfa单源最短路:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<stdlib.h>
    #include<queue>
    #include<algorithm>
    using namespace std;
    #define MAXN 500100
    #define ll long long
    queue<int> q;
    int dis[MAXN],have[MAXN];
    struct edge{
        int first;
        int next;
        int to;
        int quan;
    }a[MAXN+10];
    int num=0,n,m,S;
    
    void addedge(int from,int to,int quan){
        a[++num].to=to;
        a[num].quan=quan;
        a[num].next=a[from].first;
        a[from].first=num;
    }
    
    void spfa(int s){
        while(!q.empty()) q.pop();
        for(int i=1;i<=n;i++) dis[i]=2147483647;
        //memset(dis,127,sizeof(dis));
        memset(have,0,sizeof(have));
        have[s]=1,dis[s]=0;
        q.push(s);
        while(!q.empty()){
            int now=q.front();
            q.pop();
            have[now]=0;
            for(int i=a[now].first;i;i=a[i].next){
                int to=a[i].to,quan=a[i].quan;
                if(dis[to]>dis[now]+quan){
                    dis[to]=dis[now]+quan;
                    if(!have[to]){
                        have[to]=1;
                        q.push(to);
                    }
                }
            }
        }
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&S);
        for(int i=1;i<=m;i++){
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            addedge(x,y,z);
        }
        spfa(S);
        for(int i=1;i<=n;i++){
            printf("%d ",dis[i]);
        }
    }

       dij单源最短路:

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define MAXN 500010
    #define inf 2147483647
    using namespace std;
    struct edge{
        int first;
        int next;
        int to;
        int quan;
    }a[MAXN];
    struct node{
        int d,id;
        bool operator < (const node &x) const{
            return x.d<d;
        }
    };
    priority_queue<node> q;
    int dis[MAXN],have[MAXN];
    int n,m,S;int num=0;
    
    void addedge(int from,int to,int quan){
        a[++num].to=to;
        a[num].quan=quan;
        a[num].next=a[from].first;
        a[from].first=num;
    }
    
    void dij(){
        while(!q.empty()) q.pop();
        memset(have,0,sizeof(have));
        for(int i=1;i<=n;i++) dis[i]=inf;
        dis[S]=0;q.push((node){0,S});
        while(!q.empty()){
            int now=q.top().id;
            q.pop();
            if(have[now]) continue;
            have[now]=1;
            for(int i=a[now].first;i;i=a[i].next){
                int to=a[i].to,quan=a[i].quan;
                if(dis[to]>dis[now]+quan){
                    dis[to]=dis[now]+quan;
                    q.push((node){dis[to],to});
                }
            }
        }
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&S);
        for(int i=1;i<=m;i++){
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            addedge(x,y,z);
        }
        dij(); 
        for(int i=1;i<=n;i++){
            printf("%d ",dis[i]);
        }
    }

    P3366 【模板】最小生成树

    题目描述

    如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz

    输入输出格式

    输入格式:

    第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

    接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

    输出格式:

    输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz

    输入输出样例

    输入样例#1: 复制
    4 5
    1 2 2
    1 3 2
    1 4 3
    2 3 4
    3 4 3
    输出样例#1: 复制
    7

    说明

    时空限制:1000ms,128M

    数据规模:

    对于20%的数据:N<=5,M<=20

    对于40%的数据:N<=50,M<=2500

    对于70%的数据:N<=500,M<=10000

    对于100%的数据:N<=5000,M<=200000

    样例解释:

    所以最小生成树的总边权为2+2+3=7

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<stdio.h>
    #include<queue>
    using namespace std;
    #define MAXN 200010
    struct edge{
        int from,to,quan;
        void read(){
            scanf("%d%d%d",&from,&to,&quan);
        }
    }e[MAXN*2];
    int fa[MAXN];
    int n,m;
    
    int find(int now){
        if(fa[now]!=now) fa[now]=find(fa[now]);
        return fa[now];
    }
    
    bool cmp(edge x,edge y){
        if(x.quan<y.quan) return 1;
        return 0;
    }
    
    int main(){
        cin>>n>>m;
        for(int i=1;i<=m;i++) e[i].read();
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++){
            int x=e[i].from,y=e[i].to;
            if(find(x)!=find(y)){
                int xx=find(x),yy=find(y);
                fa[yy]=xx;
            }
        }
        int hh=find(1);
        for(int i=1;i<=n;i++) if(find(i)!=hh){
            puts("orz");return 0;
        }
        for(int i=1;i<=n;i++) fa[i]=i;
        sort(e+1,e+m+1,cmp);int ans=0,num=0;
        for(int i=1;i<=m;i++){
            int x=e[i].from,y=e[i].to,z=e[i].quan;
            if(find(x)!=find(y)){
                num++,ans+=z;
                int xx=find(x),yy=find(y);
                fa[xx]=yy;
            }
            if(num==n-1) break;
        }
        printf("%d",ans);
    }

    P3367 【模板】并查集(洛谷)

    题目描述

    如题,现在有一个并查集,你需要完成合并和查询操作。

    输入输出格式

    输入格式:

     

    第一行包含两个整数N、M,表示共有N个元素和M个操作。

    接下来M行,每行包含三个整数Zi、Xi、Yi

    当Zi=1时,将Xi与Yi所在的集合合并

    当Zi=2时,输出Xi与Yi是否在同一集合内,是的话输出Y;否则话输出N

     

    输出格式:

     

    如上,对于每一个Zi=2的操作,都有一行输出,每行包含一个大写字母,为Y或者N

     

    输入输出样例

    输入样例#1: 复制
    4 7
    2 1 2
    1 1 2
    2 1 2
    1 3 4
    2 1 4
    1 2 3
    2 1 4
    输出样例#1: 复制
    N
    Y
    N
    Y

     

     

     

     

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据,N<=10,M<=20;

    对于70%的数据,N<=100,M<=1000;

    对于100%的数据,N<=10000,M<=200000

     

    题解:

      复习一下模板,感觉自己的代码风格变了好多,而且手也生了。

     

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<stdlib.h>
    using namespace std;
    #define MAXN 10010
    int fa[MAXN];
    int n,m;
    
    int find(int now){
        if(fa[now]!=now) fa[now]=find(fa[now]);
        return fa[now];
    }
    
    void hebin(int x,int y){
        int fax=find(x),fay=find(y);
        if(fax==fay) return; 
        fa[fax]=fay;
    }
    
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++){
            int x,y,id;
            scanf("%d%d%d",&id,&x,&y);
            if(id==1) hebin(x,y);
            else{
                if(find(x)==find(y)) printf("Y
    ");
                else printf("N
    ");
            }
        }
    } 

     

    P3387 【模板】缩点(洛谷)

    题目背景

    缩点+DP

    题目描述

    给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

    允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。

    输入输出格式

    输入格式:

    第一行,n,m

    第二行,n个整数,依次代表点权

    第三至m+2行,每行两个整数u,v,表示u->v有一条有向边

    输出格式:

    共一行,最大的点权之和。

    输入输出样例

    输入样例#1: 复制
    2 2
    1 1
    1 2
    2 1
    输出样例#1: 复制
    2

    说明

    n<=10^4,m<=10^5,点权<=1000

    算法:Tarjan缩点+DAGdp

    题解:
      果然好久没敲代码了,板子敲错了3个地方,这个题目只要缩点,然后求DAG最大路就可以了。

    代码:

    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<stdio.h>
    #include<stdlib.h>
    #include<cstring>
    #include<stack>
    using namespace std;
    #define MAXN 100010
    #define ll long long
    int xx[MAXN],yy[MAXN];
    ll dp[MAXN],quan[MAXN];bool b[MAXN];
    int dfn[MAXN],low[MAXN],fa[MAXN],in[MAXN];ll w[MAXN];
    int n,m,num1=0,num2=0,num3=0;
    stack<int> s;
    
    struct edge{
        int first;
        int from;
        int to;
        int next;
    }a[MAXN];
    
    void addedge(int from,int to){
        a[++num1].to=to;
        a[num1].next=a[from].first;
        a[from].first=num1;
    }
    
    void trajian(int now){
        s.push(now);in[now]=1;
        dfn[now]=low[now]=++num2;
        for(int i=a[now].first;i;i=a[i].next){
            int to=a[i].to;
            if(!dfn[to]){
                trajian(to);
                low[now]=min(low[now],low[to]);
            }
            else if(in[to]) low[now]=min(low[now],dfn[to]);
        }
        if(dfn[now]==low[now]){
            int u=-1;num3++;
            while(u!=now){
                u=s.top();s.pop();in[u]=0;
                fa[u]=num3;w[num3]+=quan[u];
            }
        }
    }
    
    void make(){
        memset(a,0,sizeof(a));num1=0;
        for(int i=1;i<=m;i++){
            if(fa[xx[i]]!=fa[yy[i]]) 
            addedge(fa[xx[i]],fa[yy[i]]);
        }
    }
    
    void pre(){
        while(!s.empty()) s.pop();
        for(int i=1;i<=n;i++) if(!dfn[i]) trajian(i);
        make();
    }
    
    int DP(int now){
        if(b[now]) return dp[now];
        b[now]=1;dp[now]+=w[now];
        int add=0;
        for(int i=a[now].first;i;i=a[i].next){
            int to=a[i].to;
            add=max(add,DP(to));
        }
        dp[now]+=add;
        return dp[now];
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lld",&quan[i]);
        for(int i=1;i<=m;i++){
            int x,y;scanf("%d%d",&x,&y);xx[i]=x,yy[i]=y;
            addedge(x,y); 
        }
        pre();
        for(int i=1;i<=num3;i++) if(!b[i]) DP(i);
        ll ans=0;for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
        printf("%lld
    ",ans);
    }

    P1226 【模板】快速幂||取余运算(洛谷)

    题目描述

    输入b,p,k的值,求b^p mod k的值。其中b,p,k*k为长整型数。

    输入输出格式

    输入格式:

    三个整数b,p,k.

    输出格式:

    输出“b^p mod k=s”

    s为运算结果

    输入输出样例

    输入样例#1: 复制
    2 10 9
    
    输出样例#1: 复制
    2^10 mod 9=7



    题解:
      快速幂板子,注意特判底数和模数。

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define  ll long long
    
    ll a,b,mod;
    
    ll po(ll x,ll y){
        ll ans=1;
        while(y){
            if(y&1)    ans=ans*x%mod;
            x=x*x%mod;y>>=1;
        }
        return ans;
    }
    
    int main(){    
        scanf("%lld%lld%lld",&a,&b,&mod);
        if(a==0||mod==1){
            printf("%lld^%lld mod %lld=0",a,b,mod);return 0;
        }
        ll x=po(a,b);
        printf("%lld^%lld mod %lld=%lld",a,b,mod,x);
        return 0;
    } 

    P3383 【模板】线性筛素数(洛谷)

    题目描述

    如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内)

    输入输出格式

    输入格式:

    第一行包含两个正整数N、M,分别表示查询的范围和查询的个数。

    接下来M行每行包含一个不小于1且不大于N的整数,即询问该数是否为质数。

    输出格式:

    输出包含M行,每行为Yes或No,即依次为每一个询问的结果。

    输入输出样例

    输入样例#1: 复制
    100 5
    2
    3
    4
    91
    97
    输出样例#1: 复制
    Yes
    Yes
    No
    No
    Yes

    说明

    时空限制:500ms 128M

    数据规模:

    对于30%的数据:N<=10000,M<=10000

    对于100%的数据:N<=10000000,M<=100000

    样例说明:

    N=100,说明接下来的询问数均不大于100且不小于1。

    所以2、3、97为质数,4、91非质数。

    故依次输出Yes、Yes、No、No、Yes。

    题解:

      没有什么好说的,复习一下模板。

    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<queue>
    #include<cstring>
    using namespace std;
    #define ll long long
    #define MAXN 10000010
    
    int b[MAXN],su[MAXN];
    int n,q,ans;
    
    void shai(){
        for(int i=0;i<=n;i++) b[i]=1;
        b[0]=b[1]=0;
        for(int i=2;i<=n;i++){
            if(b[i]){
                ans++;
                for(int j=2*i;j<=n;j+=i) b[j]=0;
            }
        }
    }
    
    int main(){
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout); 
        scanf("%d%d",&n,&q);
        shai();
        while(q--){
            int x;scanf("%d",&x);
            if(b[x]) puts("Yes");
            else puts("No");
        }
        return 0;
    } 

    P3375 【模板】KMP字符串匹配(洛谷)

    题目描述

    如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。

    为了减少骗分的情况,接下来还要输出子串的前缀数组next。

    (如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。)

    输入输出格式

    输入格式:

    第一行为一个字符串,即为s1

    第二行为一个字符串,即为s2

    输出格式:

    若干行,每行包含一个整数,表示s2在s1中出现的位置

    接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。

    输入输出样例

    输入样例#1: 复制
    ABABABC
    ABA
    输出样例#1: 复制
    1
    3
    0 0 1 
    

    说明

    时空限制:1000ms,128M

    数据规模:

    设s1长度为N,s2长度为M

    对于30%的数据:N<=15,M<=5

    对于70%的数据:N<=10000,M<=100

    对于100%的数据:N<=1000000,M<=1000000

    样例说明:

    所以两个匹配位置为1和3,输出1、3

    题解:

      模板,可以参考其他一些书。

    代码:

    // luogu-judger-enable-o2
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #define MAXN 1000010
    using namespace std;
    char s1[MAXN],s2[MAXN];
    int len1,len2;int f[MAXN];
    
    int main()
    {
        scanf("%s%s",s1+1,s2+1);
        len1=strlen(s1+1),len2=strlen(s2+1);
        f[1]=f[2]=1;
        for(int i=2;i<=len2;i++){
            int j=f[i];
            while(j!=1&&s2[j]!=s2[i]) j=f[j];
            if(s2[i]==s2[j]) f[i+1]=j+1;
            else f[i+1]=1;
        }
        int j=1;
        for(int i=1;i<=len1;i++){
            while(j!=1&&s1[i]!=s2[j]) j=f[j];
            if(s1[i]==s2[j]) j++;
            if(j==len2+1){
                printf("%d
    ",i-len2+1);
            }
        }
        for(int i=2;i<=len2+1;i++){
            printf("%d ",f[i]-1);
        }
        return 0;
    }

    2852 [USACO06DEC]牛奶模式Milk Patterns(洛谷)

    题目描述

    Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.

    To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns -- 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.

    Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.

    农夫John发现他的奶牛产奶的质量一直在变动。经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠。我们称之为一个“模式”。 John的牛奶按质量可以被赋予一个0到1000000之间的数。并且John记录了N(1<=N<=20000)天的牛奶质量值。他想知道最长的出现了至少K(2<=K<=N)次的模式的长度。比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次。当K=2时,这个长度为4。

    输入输出格式

    输入格式:

    Line 1: Two space-separated integers: N and K

    Lines 2..N+1: N integers, one per line, the quality of the milk on day i appears on the ith line.

    输出格式:

    Line 1: One integer, the length of the longest pattern which occurs at least K times

    输入输出样例

    输入样例#1: 复制
    8 2
    1
    2
    3
    2
    3
    2
    3
    1
    输出样例#1: 复制
    4

    题解:
      就是求出现超过k次的字串的最大长度,先哈希一下,直接二分答案,然后用map统计一下字串出现次数就可以了。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <map>
    #define MAXN 100100
    #define bas 131
    #define ull unsigned long long
    using namespace std;
    int n,k;
    ull ha[MAXN],pw[MAXN];int s1[MAXN];
    map<ull,int> mp;
    
    void pre(){
        pw[0]=1,ha[0]=0;
        for(int i=1;i<=n;i++) pw[i]=pw[i-1]*bas;
        for(int i=1;i<=n;i++)
            ha[i]=ha[i-1]*bas+s1[i];
    }
    
    ull gethaxi(int l,int r){
        return ha[r]-ha[l]*pw[r-l];
    }
    
    bool check(int len){
        mp.clear();
        for(int i=0;i<=n;i++){
            if(i+len<=n){
                mp[gethaxi(i,i+len)]++;
            }
        }
        for(int i=1;i<=n;i++){
            if(mp[gethaxi(i,i+len)]>=k){
                return 1;
            }
        }
        return 0;
    }
    
    void erfen(){
        int l=1,r=n,mid,ans=0;
        while(l<=r){
            mid=(l+r)/2;
            if(check(mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d
    ",ans);
    }
    
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%d",&s1[i]);
        }
        pre();
        erfen();
        return 0;
    }
  • 相关阅读:
    Microsoft NNI入门
    【神经网络搜索】Efficient Neural Architecture Search
    Sphinx 快速构建工程文档
    Ubuntu16.04 Cuda11.1 Cudnn8.1 Tensorflow2.4 PyTorch1.7环境配置
    【CV中的Attention机制】ShuffleAttention
    【有趣的NAS】NAS-RL(ICLR2017)
    分类器
    将url下载到本地
    缓存管理器
    大数据数据结构-分类模型
  • 原文地址:https://www.cnblogs.com/renjianshige/p/9309480.html
Copyright © 2011-2022 走看看