zoukankan      html  css  js  c++  java
  • 10.21 模拟赛

    第一次140,好好的200

    mmp 因为T1少写一个取MOD

    T1:

    一棵黑白树,已知原先树上共n 个点,每个点都是黑点或者白点,切去若干条边后,分成的若干个连通子树中每块恰有一个黑点,请问有多少种切树的方案满足这个条件

    两种方案不同当且仅当存在一条边在其中一个方案中被切而在另一个方案中没被切

    思路:

    树形dp

    设dp i 0/1 表示第i个节点,它向上贡献0/1个黑点的方案数

    对于每个节点

    若它为白色

    则dp i 0 可以转移为它的子节点的dp  0值之积

    dp i 1 可以转移为它的dp 0 值除以每个子节点的白色再乘以该节点的黑色的和 因为你要从子节点里找一个黑的拉出来

    若它为黑色

    则dp i 1 可以转移为它的子节点的dp  0值之积

    dp i 0 等于它的dp i 1 因为这个点贡献只能贡献它自己

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cstdlib>
     7 #include<vector>
     8 #include<queue>
     9 #define ll long long
    10 #define inf 2147483611
    11 #define MAXN 101010
    12 #define MOD 1000000007
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n;
    22 int first[MAXN],next[2*MAXN],to[2*MAXN],cnt,f[MAXN][2];
    23 bool k[MAXN];
    24 void add(int u,int v) {next[++cnt]=first[u],first[u]=cnt,to[cnt]=v;}
    25 void exgcd(ll a,ll b,ll& d,ll& x,ll& y)
    26 {
    27     if(!b) {d=a,x=1,y=0;}
    28     else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}
    29 }
    30 ll inv(ll a, ll p)
    31 {
    32     ll d,x,y;
    33     exgcd(a,p,d,x,y);
    34     return d==1?(x+p)%p:-1;
    35 }
    36 void dp(int x,int fa)
    37 {
    38     if(k[x])
    39     {
    40         f[x][1]=f[x][0]=1;
    41         for(int i=first[x];i;i=next[i])
    42         {
    43             if(to[i]==fa) continue;
    44             dp(to[i],x);
    45             if(f[to[i]][0]) (f[x][1]*=f[to[i]][0])%=MOD;
    46         }
    47         f[x][0]=f[x][1];
    48     }
    49     else
    50     {
    51         f[x][1]=0,f[x][0]=1;
    52         for(int i=first[x];i;i=next[i])
    53         {
    54             if(to[i]==fa) continue;
    55             dp(to[i],x);
    56             if(f[to[i]][0]) (f[x][0]*=f[to[i]][0])%=MOD;
    57         }
    58         for(int i=first[x];i;i=next[i])
    59         {
    60             if(to[i]==fa) continue;
    61             if(f[to[i]][1]) (f[x][1]+=((f[x][0]*inv(f[to[i]][0],MOD))%MOD*f[to[i]][1])%MOD)%=MOD;
    62         }
    63         (f[x][0]+=f[x][1])%=MOD;
    64     }
    65 }
    66 int main()
    67 {
    68     freopen("cut.in","r",stdin);
    69     freopen("cut.out","w",stdout);
    70     n=read();
    71     int a,b;
    72     for(int i=1;i<=n;i++) {a=read(),k[i]=a;}
    73     for(int i=1;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);}
    74     dp(1,0);
    75     printf("%d",f[1][1]);
    76 }
    View Code

    orz 因为有取模和除法,所以搞了一个逆元

    T2:

    一张连通无向图,起点1号点,终点n 号点,每条道路有一个困难度vi,定义一条路径的疲劳度为他路上经过的所有道路的困难度的最大值

    一开始有k 点体力,在通过一条道路时,他可以选择消耗若干点体力值,每消耗一点,道路的困难度也会降低1

    但一条道路的困难度不能低于0 求这次从1到n的最小疲劳度

    思路:

    二分答案 

    对于每个二分出来的疲劳值,我们把所有边的困难度都减去这个值,然后跑一下最短路

    看看最后dis n是否<=k

    若<=k则疲劳度还可以更小

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cstdlib>
     7 #include<vector>
     8 #include<queue>
     9 #define ll long long
    10 #define inf 2147483611
    11 #define MAXN 50101
    12 using namespace std;
    13 inline int read()
    14 {
    15     int x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    18     return x*f;
    19 }
    20 int n,m,k;
    21 int first[MAXN],next[2*MAXN],to[2*MAXN],val[2*MAXN],aval[2*MAXN],cnt,dis[MAXN];
    22 bool vis[MAXN];
    23 void add(int u,int v,int d) {next[++cnt]=first[u],first[u]=cnt,to[cnt]=v,val[cnt]=d;}
    24 void spfa()
    25 {
    26     queue<int> q;
    27     memset(dis,127,sizeof(dis));
    28     memset(vis,0,sizeof(vis));
    29     q.push(1);vis[1]=1;dis[1]=0;
    30     while(!q.empty())
    31     {
    32         int tmp=q.front();
    33         q.pop();
    34         vis[tmp]=0;
    35         for(int i=first[tmp];i;i=next[i])
    36             if(dis[to[i]]>dis[tmp]+aval[i])
    37             {
    38                 dis[to[i]]=dis[tmp]+aval[i];
    39                 if(!vis[to[i]]) {vis[to[i]]=1;q.push(to[i]);}
    40             }
    41     }
    42 }
    43 int main()
    44 {
    45     freopen("bicycling.in","r",stdin);
    46     freopen("bicycling.out","w",stdout);
    47     n=read(),m=read(),k=read();
    48     int a,b,c;
    49     int l=0,r=0,mid;
    50     for(int i=1;i<=m;i++) {a=read(),b=read(),c=read();add(a,b,c);add(b,a,c);r=max(r,c);}
    51     while(l<r-1)
    52     {
    53         mid=(l+r)>>1;
    54         for(int i=1;i<=cnt;i++) aval[i]=max(val[i]-mid,0);
    55         spfa();
    56         if(dis[n]<=k) r=mid;
    57         else l=mid;
    58     }
    59     printf("%d",r);
    60 }
    View Code

     T3:

    结论题

    防ak好题

  • 相关阅读:
    蜂窝网格的坐标以及寻路
    unity3d 第三人称视角的人物移动以及相机控制
    基本HTML结构
    平衡二叉树
    STL基础复习
    递归
    unity 傅老师学习
    blender基础操作
    最小生成树
    最短路径
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7704689.html
Copyright © 2011-2022 走看看