zoukankan      html  css  js  c++  java
  • 某模拟题题解

    描述(A 输入文件 : A.input 输出文件 : A.output)
    一个城市的构成是一颗n 个节点的树(2 ≤ n ≤ 200), 现在需要在树中找出两条不相交的路
    径(即两条路径不能有重边也不能有重点),使得路径的长度的乘积最大。
    输入描述
    第一行一个数n 表示这个城市一共有 n 个节点。
    接下来 n-1 行,每行两个数ai 和bi (1 ≤ ai,bi ≤ n ),分别表示从ai 到bi,有一条边,每条边
    的长度为1。
    输出描述
    输出一行一个数表示两条路径长度最大的乘积。
    样例数据
    样例输入1:
    7
    1 2
    1 3
    1 4
    1 5
    1 6
    1 7
    样例输出1:
    0
    样例输入2:
    6
    1 2
    2 3
    2 4
    5 4
    6 4
    样例输出2:
    4


      第一题没多大技术含量,枚举每一条边,把这棵树分成两棵子树,再在这两棵子树上求最大的路径,这里用两种

    方法,第一种是树规,第二种是两次dfs,第一种这里就不讲了,就说第二种,首先从一个点开始深搜,找到一个离当

    前点最远的一个点,再从这个点开始,找到一个离这个点最远的点,这两个点的距离是最远的。

      然后两部分都执行以下这个,找出这个距离,相乘,不断更新结果就行了

    Code

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cctype>
     6 #include<vector>
     7 using namespace std;
     8 typedef bool boolean;
     9 template<typename T>
    10 inline void readInteger(T& u){
    11     char x;
    12     while(!isdigit((x = getchar())));
    13     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
    14     ungetc(x, stdin);
    15 }
    16 typedef class Edge{
    17     public:
    18         int end;
    19         int next;
    20         Edge(const int end = 0, const int next = 0):end(end),next(next){}
    21 }Edge;
    22 int ce;
    23 int *h;
    24 Edge* edge;
    25 inline void addEdge(int from, int end){
    26     edge[++ce] = Edge(end, h[from]);
    27     h[from] = ce;
    28 }
    29 int n;
    30 int maxd;
    31 int noded;
    32 void dsearch(int node, int split, int depth, int last){
    33     for(int i = h[node]; i != 0; i = edge[i].next){
    34         if(i == split || i == split + 1 || edge[i].end == last)    continue;
    35         dsearch(edge[i].end, split, depth + 1, node);
    36     }
    37     if(maxd <= depth){
    38         maxd = depth;
    39         noded = node;
    40     }
    41 }
    42 int farSearch(int node, int split){
    43     dsearch(node, split, 0, 0);
    44     int buf = noded;
    45     maxd = 0;
    46     dsearch(buf, split, 0, 0);
    47     return maxd;
    48 }
    49 inline void init(){
    50     readInteger(n);
    51     edge = new Edge[(const int)(2 * n + 1)];
    52     h = new int[(const int)(n + 1)];
    53     memset(h, 0, sizeof(int) * (n + 1));
    54     for(int i = 1, a, b; i < n; i++){
    55         readInteger(a);
    56         readInteger(b);
    57         addEdge(a, b);
    58         addEdge(b, a);
    59     }
    60 }
    61 inline void solve(){
    62     long long result = 0;
    63     long long a, b;
    64     for(int i = 1; i <= n; i++){
    65         for(int j = h[i]; j != 0; j = edge[j].next){
    66             if((j & 1) == 0)    continue;
    67             a = farSearch(i, j);
    68             maxd = 0;
    69             b = farSearch(edge[j].end, j);
    70             maxd = 0;
    71             result = max(result, a * b);
    72         }
    73     }
    74     cout<<result;
    75 }
    76 int main(){
    77     freopen("A.input", "r", stdin);
    78     freopen("A.output", "w", stdout);
    79     init();
    80     solve();
    81     return 0;
    82 }

    描述(B 输入文件 : B.input 输出文件 : B.output)
    有n 个人需要看医生, 其中第i 个人需要看医生的次数是ai, 一开始从1 到n 依次排列组成
    一个等待队伍, 每个人依次看医生, 那么每个人看完医生有两种情况, 第一种情况:他
    已经看够他需要看医生的次数,那么他会离开。第二种情况:他还需要看医生,那么他就
    会选择重新站在队伍的最后。选择医生想知道,当他看过k 次病人之后,这个等待队伍是
    什么样。
    输入描述
    第一行两个正整数 n 和 k (1 ≤ n ≤ 105, 0 ≤ k ≤ 1014)
    第二行一共个n 正整数 a1, a2, ..., an (1 ≤ ai ≤ 109),用空格隔开。
    输出描述
    一行,按队列的顺序输出需要的结果,每两个数之间用空格隔开,注意不要输出多余的空
    格。数据保证此时队列里至少有一个人。
    样例数据
    样例输入1:
    3 3
    1 2 1
    样例输出1:
    2
    样例输入2:
    7 10
    1 3 3 1 2 3 1
    样例输出2:
    6 2 3


      这道含金量不大,主要是这坑人的数据范围。。。O(k)的算法都会TLE,怎么办?不断把k减小,

    首先从小到大排个序,然后看k次后排序后的第i个人有没有看完,看完了就把所有人已经看了的次数加上

    这个数(不直接去更新,否则速度会变慢很多),一直到最后剩下次数不能使一个人离开队列

      接着剩下的人每个人至少还可以看k / remain次,所以每个人至少看的次数还要加上这么多

    最后就直接模拟,输出。

    Code

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cctype>
     6 #include<vector>
     7 using namespace std;
     8 typedef bool boolean;
     9 template<typename T>
    10 inline void readInteger(T& u){
    11     char x;
    12     while(!isdigit((x = getchar())));
    13     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
    14     ungetc(x, stdin);
    15 }
    16 typedef class sdata{
    17     public:
    18         int _count;
    19         int times;
    20         sdata(int times = 0, int _count = 0):times(times), _count(_count){}
    21 }sdata;
    22 int n;
    23 long long k;
    24 int* a;
    25 int* b;
    26 vector<sdata> qs;
    27 inline void init(){
    28     readInteger(n);
    29     readInteger(k);
    30     a = new int[(const int)(n + 1)];
    31     b = new int[(const int)(n + 1)];
    32     for(int i = 1; i <= n; i++)
    33         readInteger(a[i]);
    34     memcpy(b, a, sizeof(int) * (n + 1));
    35 }
    36 inline void solve(){
    37     sort(b + 1, b + n + 1);
    38     int _count = 0;
    39     for(int i = 1; i <= n; i++){
    40         if(i != 1 && b[i] != b[i - 1]){
    41             qs.push_back(sdata(b[i - 1], _count));
    42             _count = 0;
    43         }
    44         _count++;
    45     }
    46     qs.push_back(sdata(b[n], _count));
    47     
    48     int remain = n;        //剩下的数量 
    49     int subed = 0;        //已经减去的值,直接修改会浪费时间 
    50     for(int t = 0; (remain * 1LL * (qs[t].times - subed)) <= k && remain > 0; t++){
    51         k -= remain * 1LL * (qs[t].times - subed);
    52         remain -= qs[t]._count;
    53         subed += qs[t].times - subed;
    54     }
    55     
    56     if(remain == 0)    return;
    57     subed += k / remain;
    58     k %= remain;
    59     
    60     for(int i = 1; i <= n; i++)    a[i] -= subed;
    61     int i;
    62     for(i = 1; i <= n && k; i++){
    63         if(a[i] <= 0)    continue;
    64         a[i]--;
    65         k--;
    66     }
    67     
    68     for(int j = i; j <= n; j++)
    69         if(a[j] > 0)    printf("%d ", j);
    70     for(int j = 1; j < i; j++)
    71         if(a[j] > 0)    printf("%d ", j);
    72 }
    73 int main(){
    74     freopen("B.input", "r", stdin);
    75     freopen("B.output", "w", stdout);
    76     init();
    77     solve();
    78     return 0;
    79 }

    描述(C 输入文件 : C.input 输出文件 : C.output)
    有n 个任务需要你去完成,这些任务分布在3 个不同的房间,编号为1,2,3, 其中有些任务
    必须在一些其他的任务完成之后才能完成。现在知道完成一个任务需要1 的时间,现在知
    从房间1 到2,2 到3,3 到1 需要1 的时间,从1 到3,2 到1,3 到2 需要2 的时间。现
    在你可以选择你一开始的房间,问完全所有任务的最短时间是多少,保证可以完成。
    输入描述
    第一行一个数 n (1 ≤ n ≤ 200) 。
    第二行 n 个数, 第i 个数 ci (1 ≤ ci ≤ 3) 表示该任务所在的房间。.
    接下来一共 n 行. 第 i 行的第一个数是 ki (0 ≤ ki ≤ n - 1),表示完成第i 个任务之前需要完
    成的任务个数,之后 ki 个正整数表示需要提前完成的任务的编号。
    输出描述
    输出一个正整数表示完成任务需要是时间。
    样例数据
    样例输入1:
    5
    2 2 1 1 3
    1 5
    2 5 1
    2 5 4
    1 5
    0
    样例输出1:
    7


      首先可以发现从1走到3,还不如从1走到2再走到3,虽然在路上花费的时间是一样的,但是可能可以处理

    更多的任务。像样思考,从某个房间开始到最后一个任务处理完毕的方案是唯一的,唯一影响结果的就是开始

    的房间,所以枚举开始的房间然后拓扑排序就行了。

    Code

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cctype>
     6 #include<queue>
     7 #include<vector>
     8 using namespace std;
     9 typedef bool boolean;
    10 template<typename T>
    11 inline void readInteger(T& u){
    12     char x;
    13     while(!isdigit((x = getchar())));
    14     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
    15     ungetc(x, stdin);
    16 }
    17 typedef class Edge{
    18     public:
    19         int end;
    20         int next;
    21         Edge(const int end = 0, const int next = 0):end(end),next(next){}
    22 }Edge;
    23 int ce;
    24 int *h;
    25 Edge* edge;
    26 int* in;
    27 inline void addEdge(int from, int end){
    28     edge[++ce] = Edge(end, h[from]);
    29     h[from] = ce;
    30     in[end]++;
    31 }
    32 int n;
    33 int* room;
    34 inline void init(){
    35     readInteger(n);
    36     room = new int[(const int)(n + 1)];
    37     edge = new Edge[(const int)(n * n / 2 + 1)];
    38     h = new int[(const int)(n + 1)];
    39     in = new int[(const int)(n + 1)];
    40     memset(h, 0, sizeof(int) * (n + 1));
    41     memset(in, 0, sizeof(int) * (n + 1));
    42     for(int i = 1; i <= n; i++)
    43         readInteger(room[i]);
    44     for(int i = 1, k, a; i <= n; i++){
    45         readInteger(k);
    46         while(k--){
    47             readInteger(a);
    48             addEdge(a, i);
    49         }
    50     }
    51 }
    52 int* deg;
    53 queue<int> que[3];
    54 inline int tp_sort(int s){
    55     deg = new int[(const int)(n + 1)];
    56     memcpy(deg, in, sizeof(int) * (n + 1));
    57     int _count = 0;
    58     for(int i = 1; i <= n; i++)
    59         if(deg[i] == 0){
    60             _count++;
    61             que[room[i] - 1].push(i);
    62         }
    63     int status = s;
    64     int result = 0;
    65     while(_count){
    66         while(!que[status].empty()){                //处理完所有可以做的任务 
    67             int u = que[status].front();
    68             que[status].pop();
    69             for(int i = h[u]; i != 0; i = edge[i].next){
    70                 deg[edge[i].end]--;
    71                 if(deg[edge[i].end] == 0){
    72                     que[room[edge[i].end] - 1].push(edge[i].end);
    73                     _count++;
    74                 }
    75             }
    76             _count--;
    77         }
    78         if(_count == 0)    break;
    79         result++;
    80         status++;
    81         if(status > 2)    status = 0;
    82     }
    83     delete[] deg;
    84     return result + n;
    85 }
    86 int main(){
    87     freopen("C.input", "r", stdin);
    88     freopen("C.output", "w", stdout);
    89     init();
    90     int result = 0xfffffff;
    91     for(int i = 0; i < 3; i++)    result = min(result, tp_sort(i));
    92     printf("%d", result);
    93     return 0;
    94 }
  • 相关阅读:
    C# Devexpress GridView获得当前活动行(选中行)的索引
    C# Devexpress GridView获得当前活动行(选中行)的索引
    计算机网络学习总结(超赞!!!)
    计算机网络学习总结(超赞!!!)
    30张图带你彻底理解红黑树
    30张图带你彻底理解红黑树
    DevExpress GridView 添加和设置右键菜单
    DevExpress GridView 添加和设置右键菜单
    数据库分离和附加 (SQL Server)
    数据库分离和附加 (SQL Server)
  • 原文地址:https://www.cnblogs.com/yyf0309/p/5818865.html
Copyright © 2011-2022 走看看