uva 11157 - Dynamic Frog (二分 + 最大流)

题目描述了一只名为Fred的青蛙需要跳过河中不同大小的石头到达对岸并返回,小石头只能承受一次重量,大石头可以多次使用。目标是最小化青蛙的最大跳跃距离。输入包含测试用例数量T和每个案例的石头信息,包括石头类型(大或小)和位置。输出每个案例中最小化的最大跳跃距离。解题方法可以使用最大流算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D

Next Generation Contest 3

Time Limit: 2 seconds

Dynamic Frog

 

With the increased use of pesticides, the local streams and rivers have become so contaminated that it has become almost impossible for the aquatic animals to survive.

Frog Fred is on the left bank of such a river. N rocks are arranged in a straight line from the left bank to the right bank. The distance between the left and the right bank is D meters. There are rocks of two sizes. The bigger ones can withstand any weight but the smaller ones start to drown as soon as any mass is placed on it. Fred has to go to the right bank where he has to collect a gift and return to the left bank where his home is situated.

He can land on every small rock at most one time, but can use the bigger ones as many times as he likes. He can never touch the polluted water as it is extremely contaminated.

Can you plan the itinerary so that the maximum distance of a single leap is minimized?

 

Input

The first line of input is an integer T(T<100) that indicates the number of test cases. Each case starts with a line containing two integersN(0≤N≤100)and D(1≤D≤1000000000). The next line gives the description of the N stones. Each stone is defined by S-MSindicates the type Big(B) or Small(S) and M(0<M<D) determines the distance of that stone from the left bank. The stones will be given in increasing order of M.

Output

For every case, output the case number followed by the minimized maximum leap.

Sample Input

Output for Sample Input

3
1 10
B-5
1 10
S-5
2 10
B-3 S-6
Case 1: 5
Case 2: 10
Case 3: 7

 

Problem Setter: Sohel Hafiz

Special Thanks: Jane Alam Jan

这题貌似有很多种做法,dp,贪心,贪心我不知道该怎么证明,然后看n只有100,,写了个最大流过了。貌似出题人的标程也是用最大流写的。

#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <iostream>
#include <stack>
#include <set>
#include <cstring>
#include <stdlib.h>
#include <cmath>
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 200 + 5;
const int INF = 1000000000;

struct Edge {
  int from, to, cap, flow;
};

struct Dinic {
  int n, m, s, t;
  vector<Edge> edges;    // 边数的两倍
  vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
  bool vis[maxn];        // BFS使用
  int d[maxn];           // 从起点到i的距离
  int cur[maxn];         // 当前弧指针

  void ClearAll(int n) {
    for(int i = 0; i < n; i++) G[i].clear();
    edges.clear();
  }

  void ClearFlow() {
    for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
  }

  void AddEdge(int from, int to, int cap) {
    //cout << from << ' ' << to << ' ' << cap << endl;
    edges.push_back((Edge){from, to, cap, 0});
    edges.push_back((Edge){to, from, 0, 0});
    m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
  }

  bool BFS() {
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(s);
    vis[s] = 1;
    d[s] = 0;
    while(!Q.empty()) {
      int x = Q.front(); Q.pop();
      for(int i = 0; i < G[x].size(); i++) {
        Edge& e = edges[G[x][i]];
        if(!vis[e.to] && e.cap > e.flow) {
          vis[e.to] = 1;
          d[e.to] = d[x] + 1;
          Q.push(e.to);
        }
      }
    }
    return vis[t];
  }

  int DFS(int x, int a) {
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int& i = cur[x]; i < G[x].size(); i++) {
      Edge& e = edges[G[x][i]];
      if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {
        e.flow += f;
        edges[G[x][i]^1].flow -= f;
        flow += f;
        a -= f;
        if(a == 0) break;
      }
    }
    return flow;
  }

  int Maxflow(int s, int t) {
    this->s = s; this->t = t;
    int flow = 0;
    while(BFS()) {
      memset(cur, 0, sizeof(cur));
      flow += DFS(s, INF);
    }
    return flow;
  }
};

Dinic g;

struct Node{
    int pos, kind;
    Node(int pos=0, int kind=0){
        this -> pos = pos;
        this -> kind = kind;
    }
}a[maxn];

int main(){
    int t, kase = 0;
    scanf("%d", &t);
    while(t--){
        kase++;
        int n, d;
        scanf("%d%d", &n, &d);
        a[0] = Node(0, 1);
        a[n+1] = Node(d, 1);
        for(int i = 1;i <= n;i++){
            char s[5];int pos, kind;
            scanf("%1s-%d",s, &pos);
            if(s[0] == 'B'){
                a[i] = Node(pos, 1);
            }
            else{
                a[i] = Node(pos, 0);
            }
        }
        int l = 0, r = d;
        int ans = d;
        while(l <= r){
            int mid = (r+l)/2;
            g.ClearAll(2*n+5);
            int source = 0, sink = 2*n+3;
            for(int i = 0;i <= n+1;i++){
                if(a[i].kind == 1){
                    g.AddEdge(i, i+n+2, INF);
                }
                else{
                    g.AddEdge(i, i+n+2, 1);
                }
                for(int j = i+1;j <= n+1;j++){
                    if(a[j].pos-a[i].pos <= mid){
                        g.AddEdge(i+n+2, j, INF);
                    }
                }
            }
            if(g.Maxflow(source, sink) >= 2){
                ans = mid;
                r = mid-1;
            }
            else
                l = mid+1;
        }
        printf("Case %d: %d\n", kase , ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值