Street Race

图一:有 10 个路口的街道

一个良好的跑道具有如下几个特点:

  • 每一个路口都可以由起点到达。
  • 从任意一个路口都可以到达终点。
  • 终点不通往任何路口。

运动员不必经过所有的路口来完成比赛。有些路口却是选择任意一条路线都必须到达的(称为“不可避免”的)。在上面的例子中,这些路口是 0,3,6,9。对于给出的良好的跑道,你的程序要确定“不可避免”的路口的集合,不包括起点和终点。

假设比赛要分两天进行。为了达到这个目的,原来的跑道必须分为两个跑道,每天使用一个跑道。第一天,起点为路口 0,终点为一个“中间路口”;第二天,起点是那个中间路口,而终点为路口 N。对于给出的良好的跑道,你的程序要确定“中间路口”的集合。如果良好的跑道 C 可以被路口 S 分成两部分,这两部分都是良好的,并且 S 不同于起点也不同于终点,同时被分割的两个部分满足下列条件:(1)它们之间没有共同的街道(2)S 为它们唯一的公共点,并且 S 作为其中一个的终点和另外一个的起点。那么我们称 S 为“中间路口 ”。在例子中只有路口 3 是中间路口。(6不是 因为他所分成的两部分之间有公共街道8->6 so not ok)

怎么做呢?

感觉貌似又很恼火的样子。

但是数据范围并不大。直接模拟居然就well done。

1.枚举删除的点,判断是否起点终点还联通。(找出必经点)

2.同时看此必经点是否为中间点(因为中间点一定都是必经点,代码中有分析)

 怎么看呐。?就是把分成的两部分中一部分染色,另一部分看能否染成另一颜色且不重复咯。

 所以就是dfs + 标记什么的。

好的,思路就是这样了。详细分析在代码中。

代码:

/*
ID:Andy Chen
PROG: race3
LANG: C++
*/
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <vector>
using namespace std;
bool G[101][101];
int color[101];
vector<int> ans1;
vector<int> ans2;
bool dfs(int v,int m)//是否可以走到终点
//将此点标记也相当于将此点删除
//删除后 如果起点走不到终点 说明这点就是必经点集中的一员了
{
    color[v]=1;
    if(v==m)
        return true;
    for(int i=0;i<=m;i++)
    {
        if(G[v][i]&&!color[i])
        {
            if(dfs(i,m))
                return true;
        }
    }
    return false;
}
bool dfs2(int v,int m)//是否不会遇上以前搜过的点
//也就是用来判断是否符合题目要求2 :此点是否为中间点
//1st    中间点一定是必经点 因为他把图分成两部分且互相独立
//可图本来是可以从起点到终点的
//2nd    怎么来判断?
//让dfs2 以此点为起点走之前未标记的那部分图
//如果能一直跑 不遇到color【】==1
//就说明  这点就是中间点了
//因为他们已经完全分成两个部分了
{
    if(color[v]==1)
        return false;
    color[v]=2;
    for(int i=0;i<=m;i++)
    {
        if(G[v][i]&&color[i]!=2&&!dfs2(i,m))
            return false;
    }
    return true;
}
int main()
{
    freopen("race3.in","r",stdin);
    freopen("race3.out","w",stdout);
    int a,b,m;
    m=0;
    memset(G,false,sizeof(G));
    for(int i=0;scanf("%d",&a)&&a!=-1;i++)
    {
        if(a==-2)
            continue;
        m=max(m,a);
        G[i][a]=true;
        for(int j=0;scanf("%d",&a)&&a!=-2;j++)
        {
            G[i][a]=true;
            m=max(m,a);
        }
    }//这貌似是笔者不怎么有没的神奇读入
    for(int i=1;i<m;i++)
    {
        memset(color,0,sizeof(color));
        color[i]=1;
        if(!dfs(0,m))
        {
            ans1.push_back(i);
            color[i]=0;
            if(dfs2(i,m))
                ans2.push_back(i);
        }
    }
    cout<<ans1.size();
    for(int i=0;i<ans1.size();i++)
        cout<<‘ ‘<<ans1[i];
    cout<<endl;//必经点
    cout<<ans2.size();
    for(int i=0;i<ans2.size();i++)
        cout<<‘ ‘<<ans2[i];
    cout<<endl;//中间点
    return 0;
}
时间: 2024-10-14 07:52:27

Street Race的相关文章

USACO Section 4.3 Street Race(图的连通性+枚举)

虽说是IOI'95,但是也是挺水的..for 第一问,n最大为50,所以可以直接枚举起点和终点之外的所有点,然后dfs判断是否连通:for 第二问,易知答案一定是第一问的子集,所以从第一问中的答案中枚举,也是用dfs判断. #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> #define rep(i,r) for(i

usaco Street Race

图一表示一次街道赛跑的跑道.可以看出有一些路口(用 0 到 N 的整数标号),和连接这些路口的箭头.路口 0 是跑道的起点,路口 N 是跑道的终点.箭头表示单行道.运动员们可以顺着街道从一个路口移动到另一个路口(只能按照箭头所指的方向).当运动员处于路口位置时,他可以选择任意一条由这个路口引出的街道. 图一:有 10 个路口的街道 一个良好的跑道具有如下几个特点: 每一个路口都可以由起点到达. 从任意一个路口都可以到达终点. 终点不通往任何路口. 运动员不必经过所有的路口来完成比赛.有些路口却是

【最短路】【Heap-dijkstra】Gym - 101147B - Street

按题意把图建出来跑最短路就行了.注意遮挡不会影响答案,所以不必考虑,因为走直线经过遮挡的时候,一定不会比答案更优. #include<cstdio> #include<algorithm> #include<queue> #include<cmath> #include<cstring> using namespace std; #define EPS 0.00000001 #define N 109 int T,n,H,X; int hs[N]

[RxJS] Filtering operator: single, race

Single, race both get only one emit value from the stream. Single(fn): const source = Rx.Observable.from([1,2,3,4,5]); var single = source.single( x => x === 3); /* (12345)| (source) single( x => x === 3) 3| (single) */ var sub = single.subscribe( x

BZOJ 2599: [IOI2011]Race( 点分治 )

数据范围是N:20w, K100w. 点分治, 我们只需考虑经过当前树根的方案. K最大只有100w, 直接开个数组CNT[x]表示与当前树根距离为x的最少边数, 然后就可以对根的子树依次dfs并更新CNT数组和答案. ------------------------------------------------------------------------------------------ #include<bits/stdc++.h> using namespace std; typ

[C++11 并发编程] 06 Mutex race condition

上一节中介绍了mutex的基本使用方法,使用mutex来保护共享数据并不能解决race condition带来的问题,假如我们有一个堆栈数据结构类似于std::stack它提供了5个基本操作push(),pop(),top(),empty(),和size().这里的top()操作返回栈顶元素的拷贝,这样我们就可以使用一个mutex来保护栈内部的数据.但是race codition情况下,虽然使用mutex在stack的每个接口内都对共享数据进行了保护,仍然有问题存在. #include <deq

对 Data Race Free 的理解

Data Race Free 的动机 Data Race Free 是对多线程程序 同步程度 的一种描述,假如你的多线程程序的同步程度满足 DRF 的要求,那么,你的程序会有这样一个好处: 程序在弱一致性模型下执行,执行的结果与在SC模型下执行一样 这意味着,程序员在写程序时,可以按SC模型来推断程序的执行.而程序在底层运行时,可以享受弱一致性模型带来的种种优化措施. Data Race Free 具体内容 DRF 要求多线程程序中不能有冲突的操作. 什么是冲突的操作呢? 冲突的操作是指:两个操

Data Race Free 的前世今生

Data Race Free 是多线程程序是非常重要的概念,因为Java 和 C++的内存模型都是基于 Data Race Free 的,这篇文章将介绍这个概念的由来,另一篇文章<对Data Race Free的理解>介绍它的主要思想. 事情要追溯到遥远的1979年, Lamport 在他的著名论文 How to make a multiprocessor computer that correctly executes multiprocess programs 中提出了今后在内存模型领域被

【BZOJ-2599】Race 点分治

2599: [IOI2011]Race Time Limit: 70 Sec  Memory Limit: 128 MBSubmit: 2590  Solved: 769[Submit][Status][Discuss] Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 Input 第一行 两个整数 n, k第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始) Output