Codeforces Round #328 (Div. 2) C ,D

C - The Big Race

思路

开始读半天都没读懂,后来勇敢猜测一发结论,其实就是当跑道长度在 klcm(b,w) klcm(b,w)+min(b,w) 之间时会出现tie的情况,然后考虑下边界情况就行了,这题的WA点相当多,压根儿没看到说当 p==0 的时候,输出 0/1

代码(JAVA版)
import java.util.Scanner;
import java.math.*;
import java.text.*;
public class Main 
{
      public static void main(String args[])
      {
            Scanner cin = new Scanner ( System.in );
            BigInteger t,w,b,m,r,lcm,ans,last,tmp,cnt;
            t = cin.nextBigInteger();
            w = cin.nextBigInteger();
            b = cin.nextBigInteger();
            m = w.min(b);
            r = w.gcd(b);
            lcm = w.divide(r);
            lcm = lcm.multiply(b);
            cnt = t.divide(lcm);
            last = cnt.multiply(lcm);
            ans = cnt.multiply(m).subtract(BigInteger.ONE);
            tmp = t.subtract(last).add(BigInteger.ONE);
            tmp = tmp.min(m);
            ans = ans.add(tmp);
            if(ans.equals(BigInteger.ZERO)) {
               System.out.println("0/1");//WA 点
            }
            else {
               r = ans.gcd(t);
               System.out.println(ans.divide(r)+"/"+t.divide(r));
            }
      }
}

D. Super M

思路

感觉其实是个简单题啊,就以特殊点构造一颗新的树,然后求一下这棵树的直径 d 就OK了。
具体:假设需要最后跑回到出发点的话,那么总的花费一定是 (2*新图边的数目 ) ,而这个值是定值, 所以不需要最后跑回到出发点的话,而且要求花费最小,那么就是 (2d )。

代码
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int MAX = 130000;
vector<int> adj[MAX];
int d[MAX], size[MAX];
bool mark[MAX];
void dfs(int p, int v)
{
    size[v] = 0;
    if (mark[v])
        size[v] = 1;
    for (int i = 0; i < adj[v].size(); i++)
    {
        int u = adj[v][i];
        if (u != p)
        {
            d[u] = d[v] + 1;
            dfs(v, u);
            size[v] += size[u];
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n - 1; i++)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    for (int i = 0; i < m; i++)
    {
        int v;
        cin >> v;
        v--;
        mark[v] = true;
    }
    dfs(-1, 0);
    int v = -1;
    for (int i = 0; i < n; i++)
        if (mark[i] && (v == -1 || d[v] < d[i]))
            v = i;
    memset(d, 0, sizeof(d));
    dfs(-1, v);
    int sum = 0;
    int mx = 0;
    for (int i = 0; i < n; i++)
    {
        if (size[i] > 0 && m - size[i] > 0)
            sum += 2;
        if (mark[i])
            mx = max(mx, d[i]);
    }
    for (int i = 0; i < n; i++)
        if (mark[i] && i < v && d[i] == mx)
        {
            v = i;
            break;
        }
    cout << v + 1 << "\n" << sum - mx << "\n";
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值