HLG 1540 摧毁车站【dijkstra+dfs】
题意:Colugu市有n个车站和m条路。每条路直接连接两个车站,所有的路都是单向的。为了维护空气质量,政府停用了所有军队车辆。所以军队必须乘坐巴士去机场。
两个车站之 间可能不只一条路。如果一个车站被摧毁,那么所有通向那个车站的道路都没用了。Gabiluso需要去做的是摧毁一些车站使得军队不能在k分钟内
赶到机场。一辆巴士通过一条路只需要一分钟。从1到n给所有车站编号。编号为1的车站在军营里,编号为n的车站在机场里。军队总是从编号为1的车站出发
由于有重兵把守,所以编号为1和n的车站不能被摧毁。当然那里没有一条路直接从1号车站连接到n号车站,请帮助Gabiluso计算他需要摧毁车站的最小数量,他
必须完成任务。
分析: 要使得1到n的最短距离小于K,删除的点只能是从1到n最短路径上的点,可以递归枚举最短路上去除的点的所有情况找到最优解。
#include<stdio.h> #include<string.h> #define clr(x)memset(x,0,sizeof(x)) #define maxn 55 #define INF 0x1f1f1f1f int g[maxn][maxn]; int d[maxn]; int v[maxn]; int pre[maxn]; int cut[maxn]; int n,K,mcut; void dijkstra(int *s,int &top) { clr(v); int i,u; memset(d,INF,sizeof(d)); d[1]=0; while(1) { u=-1; for(i=1;i<=n;i++) if(!cut[i]&&v[i]==0&&(d[i]<d[u]||u==-1)) u=i; if(u==-1||d[u]==INF) break; v[u]=1; for(i=1;i<=n;i++) if(!cut[i]&&v[i]==0&&g[u][i]) if(d[u]+1<d[i]) { d[i]=d[u]+1; pre[i]=u; } if(v[n]) break; } if(d[n]<=K) { top=0; i=pre[n]; while(i!=1) { s[top++]=i; i=pre[i]; } } } void dfs(int ncut) { int i,s[maxn],top; dijkstra(s,top); if(d[n]>K) { if(ncut<mcut) mcut=ncut; return; } if(mcut<=ncut+1) return; for(i=0;i<top;i++) { cut[s[i]]=1; dfs(ncut+1); cut[s[i]]=0; } } int main() { int a,b,m; while(scanf("%d%d%d",&n,&m,&K),n||m||K) { clr(g); clr(cut); mcut=INF; while(m--) { scanf("%d%d",&a,&b); g[a][b]=1; } dfs(0); printf("%d\n",mcut); } return 0; }