• 测试 10.23


    叉叉

    题目名称

    叉叉

    程序文件名

    cross

    输入文件名

    cross.in

    输出文件名

    cross.out

    每个测试点时限

    1秒

    内存限制

    128MB

    测试点数目

    10

    每个测试点分值

    10

    是否有部分分

    试题类型

    传统

     

    题目描述

    现在有一个字符串,每个字母出现的次数均为偶数。接下来我们把第一次出现的字母a和第二次出现的a连一条线,第三次出现的和四次出现的字母a连一条线,第五次出现的和六次出现的字母a连一条线...对其他25个字母也做同样的操作。

    现在我们想知道有多少对连线交叉。交叉的定义为一个连线的端点在另外一个连线的内部,另外一个端点在外部。

    下图是一个例子,共有三对连线交叉(我们连线的时候,只能从字符串上方经过)。

    输入格式

    一行一个字符串。保证字符串均由小写字母组成,且每个字母出现次数为偶数次。

    输出格式

    一个整数,表示答案。

    样例输入

    abaazooabz

    样例输出

    3

    数据范围

    对于30% 的数据,字符串长度不超过50。

    对于100% 的数据,字符串长度不超过100,000。

     思路:模拟

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    char s[100010];
    int len,ans;
    int pos[28],vis[28];
    int main(){
        freopen("cross.in","r",stdin);
        freopen("cross.out","w",stdout);
        scanf("%s",s+1);
        len=strlen(s+1);
        for(int i=1;i<=26;i++){
            int flag=0,num=0;
            memset(vis,0,sizeof(vis));
            memset(pos,-1,sizeof(pos));
            for(int j=1;j<=len;j++){
                int x=s[j]-'a'+1;
                if(s[j]-'a'+1==i&&flag){ ans+=num;flag=0;num=0; }
                else if(s[j]-'a'+1==i&&flag==0){ flag=j; }
                else if(flag){
                    if(vis[s[j]-'a'+1]){
                        vis[s[j]-'a'+1]=0;
                        if(pos[s[j]-'a'+1]<flag){ num++;pos[s[j]-'a'+1]=-1; }    
                        else{ num--;pos[s[j]-'a'+1]=-1; }
                    }
                    else{ num++;vis[s[j]-'a'+1]=1;pos[s[j]-'a'+1]=j; }
                }
                else if(flag==0){
                    if(vis[s[j]-'a'+1])    vis[s[j]-'a'+1]=0,pos[s[j]-'a'+1]=-1;
                    else vis[s[j]-'a'+1]=1,pos[s[j]-'a'+1]=j;
                }
            }
        }
        cout<<ans/2;
    }
    /*
    aaaaaaaa  0
    abababab  2
    fgshahafgs  4
    agafsdgfsd  7
    abaazooabz  3
    fgsgsfsdaads  1
    abcdacdbcabdacbd  9
    absbsbsbsddaskaksa  4
    abaaaaaaaabbbbbbbbab  3
    ghdgahsgdhasgdhasghdgasgdashgdhasgdgshs  37
    */

    思路:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 20010
    using namespace std;
    int n,m,q,k;
    int tot,tot1;
    int ans=0x7f7f7f7f;
    int dis[MAXN],vis[MAXN];
    int dis1[MAXN],vis1[MAXN];
    int to[MAXN],net[MAXN],cap[MAXN],head[MAXN];
    int to1[MAXN],net1[MAXN],cap1[MAXN],head1[MAXN];
    struct nond{
        int x,y,z;
    }edge[MAXN];
    void add(int u,int v,int w){
        to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
    }
    void add1(int u,int v,int w){
        to1[++tot1]=v;cap1[tot1]=w;net1[tot1]=head1[u];head1[u]=tot1;
    }
    void spfa(int s){
        queue<int>que;
        memset(vis,0,sizeof(vis));
        memset(dis,0x7f,sizeof(dis));
        que.push(s);
        dis[s]=0;vis[s]=1;
        while(!que.empty()){
            int now=que.front();
            que.pop();
            vis[now]=0;
            for(int i=head[now];i;i=net[i])
                if(dis[to[i]]>dis[now]+cap[i]){
                    dis[to[i]]=dis[now]+cap[i];
                    if(!vis[to[i]]){
                        vis[to[i]]=1;
                        que.push(to[i]);
                    }
                }
        }
    }
    void spfaa(int s){
        queue<int>qu;
        memset(vis1,0,sizeof(vis1));
        memset(dis1,0x7f,sizeof(dis1));
        qu.push(s);
        dis1[s]=0;vis1[s]=1;
        while(!qu.empty()){
            int now=qu.front();
            qu.pop();
            vis1[now]=0;
            for(int i=head1[now];i;i=net1[i])
                if(dis1[to1[i]]>dis1[now]+cap1[i]){
                    dis1[to1[i]]=dis1[now]+cap1[i];
                    if(!vis1[to1[i]]){
                        vis1[to1[i]]=1;
                        qu.push(to1[i]);
                    }
                }
        }
    }
    int main(){
        freopen("move.in","r",stdin);
        freopen("move.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&q,&k);
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add1(v,u,w);
        }
        for(int i=1;i<=q;i++)
            scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);
        if(k==0){
            spfa(1);
            if(dis[n]==2139062143){ cout<<"-1"; return 0; }
            else cout<<dis[n];
        }
        else if(k==1){
            spfa(1);
            spfaa(n);
            ans=dis[n];
            if(dis[n]==2139062143){ cout<<"-1"; return 0; }
            for(int i=1;i<=q;i++){
                if(dis[edge[i].x]==2139062143)    continue;
                if(dis[edge[i].y]==2139062143)    continue;
                ans=min(ans,dis[edge[i].x]+dis1[edge[i].y]+edge[i].z);
            }
            cout<<ans;
        }
        else if(k>=q){
            for(int i=1;i<=q;i++)
                add(edge[i].x,edge[i].y,edge[i].z);
            spfa(1);
            if(dis[n]==2139062143){ cout<<"-1"; return 0; }
            cout<<dis[n];
        }
        else{
            spfa(1);
            cout<<dis[n]-100;
        }
    }
    /*
    5 5 2 1
    1 2 1
    1 3 2
    2 4 2
    3 4 3
    4 5 4
    1 4 1
    2 5 1
    */
    80分暴力
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 20010
    using namespace std;
    int n,m,q,k;
    int tot,tot1;
    int ans=0x7f7f7f7f;
    int dis[MAXN],vis[MAXN];
    int dis1[MAXN],vis1[MAXN];
    int to[MAXN],net[MAXN],cap[MAXN],head[MAXN];
    int to1[MAXN],net1[MAXN],cap1[MAXN],head1[MAXN];
    struct nond{
        int x,y,z;
    }edge[MAXN];
    void add(int u,int v,int w){
        to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
    }
    void add1(int u,int v,int w){
        to1[++tot1]=v;cap1[tot1]=w;net1[tot1]=head1[u];head1[u]=tot1;
    }
    void spfa(int s){
        queue<int>que;
        memset(vis,0,sizeof(vis));
        memset(dis,0x7f,sizeof(dis));
        que.push(s);
        dis[s]=0;vis[s]=1;
        while(!que.empty()){
            int now=que.front();
            que.pop();
            vis[now]=0;
            for(int i=head[now];i;i=net[i])
                if(dis[to[i]]>dis[now]+cap[i]){
                    dis[to[i]]=dis[now]+cap[i];
                    if(!vis[to[i]]){
                        vis[to[i]]=1;
                        que.push(to[i]);
                    }
                }
        }
    }
    void spfaa(int s){
        queue<int>qu;
        memset(vis1,0,sizeof(vis1));
        memset(dis1,0x7f,sizeof(dis1));
        qu.push(s);
        dis1[s]=0;vis1[s]=1;
        while(!qu.empty()){
            int now=qu.front();
            qu.pop();
            vis1[now]=0;
            for(int i=head1[now];i;i=net1[i])
                if(dis1[to1[i]]>dis1[now]+cap1[i]){
                    dis1[to1[i]]=dis1[now]+cap1[i];
                    if(!vis1[to1[i]]){
                        vis1[to1[i]]=1;
                        qu.push(to1[i]);
                    }
                }
        }
    }
    int main(){
        freopen("move.in","r",stdin);
        freopen("move.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&q,&k);
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add1(v,u,w);
        }
        for(int i=1;i<=q;i++)
            scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);
        if(k==0){
            spfa(1);
            if(dis[n]==2139062143){ cout<<"-1"; return 0; }
            else cout<<dis[n];
        }
        else if(k==1){
            spfa(1);
            spfaa(n);
            ans=dis[n];
            if(dis[n]==2139062143){ cout<<"-1"; return 0; }
            for(int i=1;i<=q;i++){
                if(dis[edge[i].x]==2139062143)    continue;
                if(dis[edge[i].y]==2139062143)    continue;
                ans=min(ans,dis[edge[i].x]+dis1[edge[i].y]+edge[i].z);
            }
            cout<<ans;
        }
        else{
            for(int i=1;i<=q;i++)
                add(edge[i].x,edge[i].y,edge[i].z);
            spfa(1);
            if(dis[n]==2139062143){ cout<<"-1"; return 0; }
            cout<<dis[n];
        }
    }
    /*
    5 5 2 1
    1 2 1
    1 3 2
    2 4 2
    3 4 3
    4 5 4
    1 4 1
    2 5 1
    */
    非正解卡过思路

    正解:dp

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    namespace Solve
    {
        typedef pair<int,int> Node;
        const int MAXN = 500 + 10, MAXM = 2000 + 10, INF = 0x7fffffff/2;
        int n, m, q, k;
        int nodes[MAXN][MAXN], nop;
        int head[MAXN*MAXN], next[MAXN*MAXM*2], to[MAXN*MAXM*2], w[MAXN*MAXM*2], op;
        int dis[MAXN*MAXN];
    
        void build(int a, int b, int x)
        {
            next[++op]=head[a];head[a]=op;to[op]=b;w[op]=x;
        }
        int dijkstra(int s, int t, int n)
        {
            priority_queue<Node, vector<Node>, greater<Node> > que;
            
            for(int i=1;i<=n;i++) dis[i] = INF;
            dis[s] = 0;
            que.push(Node(dis[s], s));
            while(!que.empty())
            {
                Node u = que.top(); que.pop();
                if (dis[u.second] != u.first) continue;
                for(int pos=head[u.second]; pos; pos=next[pos])
                {
                    if (u.first + w[pos] < dis[to[pos]])
                    {
                        dis[to[pos]] = u.first + w[pos];
                        que.push(Node(dis[to[pos]], to[pos]));
                    }
                }
            }
    
            return dis[t] == INF ? -1 : dis[t];
        }
        void solve()
        {
            scanf("%d%d%d%d", &n, &m, &q, &k);
            k = min(k, n);
    
            nop = 0;
            for(int i=0;i<=k;i++)
                for(int u=1;u<=n;u++)
                    nodes[i][u] = ++nop;
    
            for(int i=1;i<=m;i++)
            {
                int u, v, w;
                scanf("%d%d%d", &u, &v, &w);
                for(int j=0;j<=k;j++)
                    build(nodes[j][u], nodes[j][v], w);
            }
    
            for(int i=1;i<=q;i++)
            {
                int x, y, z;
                scanf("%d%d%d", &x, &y, &z);
                for(int j=0;j<k;j++)
                    build(nodes[j][x], nodes[j+1][y], z);
            }
    
            for(int i=0;i<k;i++)
                build(nodes[i][n], nodes[i+1][n], 0);
            
            cout << dijkstra(nodes[0][1], nodes[k][n], nop) << endl;
        }
    }
    
    int main()
    {
        freopen("move.in", "r", stdin);
        freopen("move.out", "w", stdout);
    
        Solve::solve();
    
        return 0;
    }
    View Code

    思路:树形DP
    设dp[i][j]表示在i的子树中j所在的联通块的大小 为dp[i][j],其他联通块大小均符合要求的删边方案数

    然后

    求助大佬翻译一下题解:

    考虑用树形dp来解决这道问题。  
    设f[i][j] 表示在i的子树中j所在的连通块大小为f[i][j],且其他连通块大小均符合要求的删边方案数
    对于每个点??我们一棵一棵地将其子树加进来,设新加入子树的根为??
    若删除??与??之间的边,则用??[??][??] * sum(??[??][??]) s in [k,n] 去更新??[??][??]
    若不删??与??之间的边,则枚举??所在连通块的大小??,并更新??[??][??+??]
    时间复杂度 O(n^3) ?
    考虑一个优化:每次新加一颗子树时,??只需枚举到前面已经加进来的子树大小之和,??也只需枚举到新子树的大小
    这只是一个常数优化?其实每个点对相当于只在??????处被算了一次
    故优化后的时间复杂度是O(n^2)的,本题得以解决。
    #include<cstdio>
    #include<cstdlib>
    #define MAXN 5555
    #define mod 786433
    using namespace std;
    int n,K,tot;
    long long f[MAXN][MAXN];
    int to[MAXN*2],net[MAXN*2],head[MAXN];
    long long size[MAXN],g[MAXN],cnt[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;net[tot]=head[v];head[v]=tot;
    }
    void dfs(int now,int fa){
        size[now]++;
        f[now][1]=1;
        for(int i=head[now];i;i=net[i])
            if(to[i]!=fa){
                dfs(to[i],now);
                for(int j=1;j<=size[now]+size[to[i]];j++) g[j]=0;
                for(int j=1;j<=size[now];j++) g[j]=cnt[to[i]]*f[now][j]%mod;
                for(int j=1;j<=size[now];j++)
                for(int k=1;k<=size[to[i]];k++) g[j+k]=(g[j+k]+f[now][j]*f[to[i]][k]%mod)%mod;
                for(int j=1;j<=size[now]+size[to[i]];j++) f[now][j]=g[j];
                size[now]+=size[to[i]];
            }
        for(int i=K;i<=size[now];i++) cnt[now]=(cnt[now]+f[now][i])%mod;
        return ;
    }
    int main(){
        freopen("cut.in","r",stdin);
        freopen("cut.out","w",stdout);
        scanf("%d %d",&n,&K);
        for (int i=1;i<n;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            add(u,v);
        }
        dfs(1,1);
        printf("%d
    ",cnt[1]);
        return 0;
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    request.getAttribute()和 request.getParameter()的区别
    jquery中$.get()提交和$.post()提交有区别吗?
    jQuery有几种选择器?
    jQuery 库中的 $() 是什么?
    JavaScript内置可用类型
    MySQL数据库中,常用的数据类型
    简单叙述一下MYSQL的优化
    什么是JDBC的最佳实践?
    Vue官网教程-条件渲染
    Vue官网教程-Class与Style绑定
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7716734.html
Copyright © 2020-2023  润新知