poj3921
迭代加深搜索
题意:一个有向图,每条边长度为1,问要让起点到终点距离大于K,至少要删除几个点。
思路:深搜,深搜过程中每次先宽搜求最短路,若最短路大于K,则已达到条件。否则最短路上必然要有点被删掉,就依次枚举删除每个点的情况并向下深搜。用迭代加深来提速,每次限定dfs搜索的深度。
View Code
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int maxn = 60, maxm = 4005, inf = 0x3f3f3f3f; int edge[maxm], head[maxn], next[maxm]; int ncount; int n, m, minlen; bool destroyed[maxn]; void addedge(int a, int b) { edge[ncount] = b; next[ncount] = head[a]; head[a] = ncount++; } void input() { for (int i = 0; i < m; i++) { int a, b; scanf("%d%d", &a, &b); a--; b--; addedge(a, b); } } bool bfs(int station[], int &num) { int q[maxn], front = 0, rear = 0; int dist[maxn], pre[maxn]; bool vis[maxn]; memset(vis, 0, sizeof(vis)); for (int i = 0; i < n; i++) dist[i] = inf; q[rear++] = 0; dist[0] = 0; vis[0] = true; while (front != rear) { int a = q[front++]; int temp = head[a]; while (temp != -1) { int b = edge[temp]; if (!destroyed[b] && !vis[b]) { dist[b] = dist[a] + 1; pre[b] = a; q[rear++] = b; vis[b] = true; // printf("%d %d\n", b, dist[b]); } temp = next[temp]; } } if (dist[n - 1] > minlen) return true; int temp = n - 1; num = 0; while (pre[temp] != 0) { station[num++] = pre[temp]; temp = pre[temp]; } return false; } bool dfs(int step, int bottom) { if (step > bottom) return false; int station[maxn], num; if (bfs(station, num)) return true; for (int i = 0; i < num; i++) { destroyed[station[i]] = true; if (dfs(step + 1, bottom)) return true; destroyed[station[i]] = false; } return false; } int main() { // freopen("t.txt", "r", stdin); while (~scanf("%d%d%d", &n, &m, &minlen) && (n | m | minlen)) { memset(head, -1, sizeof(head)); ncount = 0; input(); for (int i = 0; i <= n - 2; i++) { memset(destroyed, 0, sizeof(destroyed)); if (dfs(0, i)) { printf("%d\n", i); break; } } } return 0; }