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;

}

你可能感兴趣的:(poj)