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;
}
原文地址:https://www.cnblogs.com/rainydays/p/2573026.html