题目总结1

There are n cities and n - 1 roads in the Seven Kingdoms, each road connects two cities and we can reach any city from any other by the roads.

Theon and Yara Greyjoy are on a horse in the first city, they are starting traveling through the roads. But the weather is foggy, so they can’t see where the horse brings them. When the horse reaches a city (including the first one), it goes to one of the cities connected to the current city. But it is a strange horse, it only goes to cities in which they weren’t before. In each such city, the horse goes with equal probabilities and it stops when there are no such cities.

Let the length of each road be 1. The journey starts in the city 1. What is the expected length (expected value of length) of their journey? You can read about expected (average) value by the link https://en.wikipedia.org/wiki/Expected_value.

Input
The first line contains a single integer n (1 ≤ n ≤ 100000) — number of cities.

Then n - 1 lines follow. The i-th line of these lines contains two integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi) — the cities connected by the i-th road.

It is guaranteed that one can reach any city from any other by the roads.

Output
Print a number — the expected length of their journey. The journey starts in the city 1.

Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

Namely: let’s assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .

Examples
Input
4
1 2
1 3
2 4
Output
1.500000000000000
Input
5
1 2
1 3
3 4
2 5
Output
2.000000000000000
暴力搜索
n点n-1边不成环,由一点开始分叉。搜索较容易想

#include<iostream>
#include<cstdio>
using namespace std;
int n;
bool vis[100001]={0};
int cnt[100001];
double ans=0;
int sum;
int k=0;
struct p
{
    int a,b;
};
p m[100001];
int f[100001]={0};
void search(int v)
{
    //if(f[v]) sum=f[v];
    //else if(cnt[v]>1){sum=sum*cnt[v];f[v]=sum;}
    if(cnt[v]==0) {ans=ans+double(k)/(sum*1.0); return;}
    if(f[v]!=0) sum=f[v];
    else if(cnt[v]>1) {sum=sum*cnt[v];f[v]=sum;}
    for(int i=1;i<n;i++)
    {
        //if(f[v]) sum=f[v];
        //else if(cnt[v]>1) sum=sum*cnt[v];
        if(m[i].a==v||m[i].b==v)
           if(vis[i]==0)
        {
            vis[i]=1;
            k++;
           // if(f[v]!=0) sum=f[v];
           // else if(cnt[v]>1){ sum=sum*cnt[v]; f[v]=sum;}
            if(v==m[i].a){ search(m[i].b);}
            else {  search(m[i].a);}
            k--;
            //if(i==n-1&&cnt[v]>1) sum=sum/cnt[v];
           vis[i]=0;
        }
        if(i==n-1&&cnt[v]>1) sum=sum/cnt[v];
    }
}
int main()
{
   cin>>n;
   int c,d;
   if(n==1) {cout<<'0'<<endl; return 0;}
   for(int i=1;i<n;i++)
   {
      cin>>c>>d;
      m[i].a=c;
      m[i].b=d;
      cnt[c]++;
      cnt[d]++;
   }
   for(int i=2;i<=n;i++)
   {
       cnt[i]=cnt[i]-1;
   }
   /*for(int i=1;i<=n;i++)
   {
       cout<<cnt[i]<<endl;
   }*/
 //  cout<<endl;
   sum=1;
   search(1);
   printf("%.15lf\n",ans);
}

弊端每次都全搜,浪费,可以用vector二维数组,减少搜索次数

#include <iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
vector<int> tree[100001];
bool vis[100001];
int n;
double ans=0;
void dfs(int v,double sum,int step)
{
    if(tree[v].size()==1&&v!=1)
    {
        ans=ans+step*sum;
        return ;
    }
       int len=tree[v].size();
       for(int i=0;i<len;i++)
       {
           int ti=tree[v][i];
           if(vis[ti]==0)
           {
               vis[ti]=1;
               if(v==1){dfs(ti,sum/len,step+1);}
               else {dfs(ti,sum/(len-1), step+1);}
           }
       }
}
int main()
{
    scanf("%d",&n);
    int a,b;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        tree[a].push_back(b);
        tree[b].push_back(a);
    }
    vis[1]=1;
    dfs(1,1,0);
    printf("%.15lf\n",ans);
    return 0;
}

好处很明显,搜索次数大大减少
有一个注意点最好不要用路径长度除以最终分叉的乘积,若分母过大啊,电脑懵逼,把他搞成0;
与之相似的一道题
You are given two strings s and t consisting of lowercase Latin letters. Also you have a string z which is initially empty. You want string z to be equal to string t. You can perform the following operation to achieve this: append any subsequence of s at the end of string z. A subsequence is a sequence that can be derived from the given sequence by deleting zero or more elements without changing the order of the remaining elements. For example, if z=ac, s=abcde, you may turn z into following strings in one operation:

z=acace (if we choose subsequence ace);
z=acbcd (if we choose subsequence bcd);
z=acbce (if we choose subsequence bce).
Note that after this operation string s doesn’t change.

Calculate the minimum number of such operations to turn string z into string t.

Input
The first line contains the integer T (1≤T≤100) — the number of test cases.

The first line of each testcase contains one string s (1≤|s|≤105) consisting of lowercase Latin letters.

The second line of each testcase contains one string t (1≤|t|≤105) consisting of lowercase Latin letters.

It is guaranteed that the total length of all strings s and t in the input does not exceed 2⋅105.

Output
For each testcase, print one integer — the minimum number of operations to turn string z into string t. If it’s impossible print −1.

Example
Input
3
aabce
ace
abacaba
aax
ty
yyt
Output
1
-1
3
暴力搜索很好想但浪费时间,所以可以和上一道题进行同样的处理,用动态二维数组来存储每一个字母的出现的书序。然后查找。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
char s[100001],t[100001];
int main()
{
    int n;
    cin>>n;
    while(n--){
        scanf("%s%s",s,t);
        vector<int>p[30];
        for(int i=0;s[i];i++)
            p[s[i]-'a'].push_back(i);
        int ans=1,flag=1;
        int pos,ppos=-1;
        for(int i=0;t[i];i++)
            {
            int k=t[i]-'a';
            if(p[k].size()==0)
                {
                flag=0;
                break;
                }
            pos=upper_bound(p[k].begin(),p[k].end(),ppos)-p[k].begin();
            if(pos==p[k].size())
                {
                ans++;
                pos=0;
                }
            ppos=p[k][pos];
           }
        if(!flag) cout<<"-1"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}

bound是一个比较好用的功能,
lower_bound( )和upper_bound( )都是在排好序的数组中使用的。

他们利用二分查找,以O(logn)的时间复杂度返回一个符合条件的索引值。下面进行解析:

非重载的lower_bound( )和upper_bound( )用于在从小到大的排序数组中的查找:

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

在从大到小的排序数组中,通过greater重载lower_bound()和upper_bound(),比如int数组就是greater:

lower_bound( begin,end,num,greater() ): 从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
————————————————
版权声明:本文为CSDN博主「Wzning0421」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hanzhen7541/article/details/99722948

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值