首页 > 代码库 > HDU 2485 求删最少点使得 边权=1的有向图最短路>k

HDU 2485 求删最少点使得 边权=1的有向图最短路>k

题意:

给定n个点 m条有向边 k

下面m条有向边

问删最少几个点使得1-n的最短路>k

10 11 5
1 2
2 3
3 4
4 5
5 10
2 9
1 6
6 7
7 8
8 9
9 10

8 10 5
1 2
2 3
3 4
4 5
5 6
6 8
1 7
7 8
4 7
7 4


#include <stdio.h>
#include <string.h>


#define N 55
#define INF 1<<30
#define eps 1e-5

int n_node, n_edge, limit, len;//len 记录广搜最短路的长度
int limit_depth;    //记录当前神搜限制的深度
bool success;       //标记是否找到答案


int que[N], road[N][N]; //que广搜时用的队列,road(i, j)表示深度为i时的广搜的最短路
int pre[N]; //pre记录广搜路径
int end[4005], head[N], next[4005], tot;  //邻接表
bool del[N];    //记录被删的点

void add_edge(int from, int to)     //add edge into adjacency list
{
    end[++tot] = to;
    next[tot] = head[from];
    head[from] = tot;
}

bool bfs()   //breadth first search
{
    for(int i = 1; i <= n_node; ++i)
        pre[i] = 0;
    int top = 0, tail = 0;
    que[++top] = 1;
    while(tail < top)
    {
        int now = que[++tail];
        for(int i = head[now]; i != -1; i = next[i])
        {
            int point = end[i];
            if(del[point] == false && pre[point] == 0)
            {
                pre[point] = now;       //记录广搜路径
                que[++top] = point;         //入队
                if(point == n_node)
                    return true;
            }
        }
    }
    return false;
}

void dfs(int dep)   //depth first search
{
    if(success == true)
        return;
    bool find = bfs();   //广搜找最短

    if(find == false)      //找不到最短路了
    {
        success = true;
        return;
    }
    int cnt = 0;    //记录最短路的长度
    //que[top]为最后一个节点,i == 1时就跳出循环,所以没有包括起点和终点
    for(int i = pre[n_node]; i != 1; i = pre[i])
        road[dep][cnt++] = i;
    if(cnt >= limit)
    {
        success = true;
        return;
    }

    if(dep > limit_depth)   //深度大于限制的深度,也就是不能再删点了
        return;

    //不可以删最后一个(i=cnt-2的点)和第一个节点(i=0的点)
    for(int i = cnt - 1; i >= 0; --i)
    {
        int del_point = road[dep][i];
        del[del_point] = true;
        dfs(dep + 1);
        del[del_point] = false;
    }
}

int main()
{
    //freopen("in.txt", "r", stdin);
    bool have[N][N];
    while(scanf("%d%d%d", &n_node, &n_edge, &limit), n_node || n_edge || limit)
    {
        tot = 0;    //邻接表下标
        memset(have, false, sizeof(have));

        for(int i = 0; i <= n_node; ++i)    //初始化
        {
            head[i] = -1;
            del[i] = false;
        }

        for(int i = 0; i < n_edge; ++i)
        {
            int from, to;
            scanf("%d%d", &from, &to);
            if(have[from][to] == false)
            {
                have[from][to] = true;
                add_edge(from, to);
            }
        }

        int m = n_node - 2;
        success = false;
        //迭代加深搜索,限制深度为i,即限制最多删i个点
        for(int i = 0; i <= m; ++i)
        {
            limit_depth = i;
            dfs(1);
            if(success == true)
                break;
        }
        printf("%d\n", limit_depth);
    }
    return 0;
}