【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了