题意:
给定n个点 m条有向边 k
下面m条有向边
问删最少几个点使得1-n的最短路>k
网上网络流的代码大概能用下面这2组数据cha掉。。
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; }