【NOIP2010 模擬賽】晨跑路徑

【NOIP2010 模擬賽】晨跑路徑

Description

天天到部隊,教官要求他們每天早上晨跑,從A農場跑到B農場。從A農場到B農場中有n-2個路口,分別標上號A農場爲1號,B農場爲n號,路口分別爲2..n-1號,從A農場到B農場有很多條路徑可以到達,而教官發現有的路口是必須經過的,即每一條路徑都經過的路口,教官要把他們記錄下來,這樣教官就可以先到達那個路口,觀察天天有沒有偷懶,而你的任務就是找所有必經路口。

Input

第一行兩個用空格隔開的整數n(3<=n<=2000)和e(1<=e<=8000)。

接下來從第2行到第e+1行,每行兩個用空格隔開的整數p和q,表示路口p和q之間連通。

輸入數據保證必經路口一定存在,並且每個路口都和A農場,B農場相連通。

Output

第一行一個整數m,表示必經路口的數目。

第二行按從小到大的順序依次輸出每個必經路口的編號,每兩個數之間用空格隔開。

注意:不包括起點和終點

Sample Input

6 6

1 2

2 4

2 3

3 5

4 5

5 6

Sample Output

2

2 5

Source

搜索 ,圖論

Solution

就是求割點的個數,可以用tarjan(無奈不會啊),於是就用了很暴力的暴力

直接枚舉每一個點,check將其斷開後是否可以到達終點,能到達即不是割點,不能到達即滿足情況,將其記錄存入數組,最後一次性輸出即可

Code

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
#include <queue>
#define L 5000
#define LL long long
using namespace std;

struct node {
  int nxt, to;
} x[L * 3];
int n, e, a, b, cnt, head[L], ans[L], num;
bool vis[L], bj;

inline void add(int from, int to) {
  x[++cnt].nxt = head[from];
  x[cnt].to = to;
  head[from] = cnt;
}

inline void dfs(int a) {
  for (int i = head[a]; i; i = x[i].nxt)
    if (!vis[x[i].to]) {
      if (x[i].to == n) {bj = false; return ;}
      vis[x[i].to] = true;
      dfs(x[i].to);
    }
}

int main() {
  freopen("running.in", "r", stdin);
  freopen("running.out", "w", stdout);
  scanf("%d %d", &n, &e);
  for (int i = 1; i <= e; ++i) {
    scanf("%d %d", &a, &b);
    add(a, b), add(b, a);
  }
  for (int i = 2; i < n; ++i) {
    bj = true;
    memset(vis, false, sizeof(vis));
    vis[i] = true;
    dfs(1);
    if (bj) ans[++num] = i;
  }
  printf("%d\n", num);
  for (int i = 1; i <= num; ++i) printf("%d ", ans[i]);
  return 0;
}

Summary

考試的時候想了很暴力的暴力:找到方案總數,以及所用方案中每個點被經過的次數,如果經過的次數等與方案總數,那麼這個點就是必須經過的點,結果只有10分

後來開始求割點,結果數組開小了WA了一次,把數組開大就A了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章