传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2485
题意:给你n个点,m条相连的边,问你最少去掉几个点使从1到n最小路径>=k,其中不能去掉1,n两个点。
题解:这个题目可以用最小流解决,也可以用IDA* + BFS解决。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cstdlib> #include <cmath> #include <vector> #include <list> #include <deque> #include <queue> #include <iterator> #include <stack> #include <map> #include <set> #include <algorithm> #include <cctype> using namespace std; #define si1(a) scanf("%d",&a) #define si2(a,b) scanf("%d%d",&a,&b) #define sd1(a) scanf("%lf",&a) #define sd2(a,b) scanf("%lf%lf",&a,&b) #define ss1(s) scanf("%s",s) #define pi1(a) printf("%d\n",a) #define pi2(a,b) printf("%d %d\n",a,b) #define mset(a,b) memset(a,b,sizeof(a)) #define forb(i,a,b) for(int i=a;i<b;i++) #define ford(i,a,b) for(int i=a;i<=b;i++) typedef long long LL; const int N=1005; const int M=105; const int INF=0x3f3f3f3f; const double PI=acos(-1.0); const double eps=1e-7; int n,m,k; int lin[N][N];//邻接表储存 int fa[N];//记录从1到n最短路径 bool vis[N];//标记节点是否被删除 int ans,Min; bool flag; struct xh { int x,y,next; }edge[N]; int bfs() { int q[2222]; int he=0,ta=0; mset(fa,-1); fa[1]=0; mset(q,0); q[ta++]=1; while(he!=ta) { int x=q[he++]; for(int i=1;i<=lin[x][0];i++) { int v=lin[x][i]; if(fa[v]==-1&&!vis[v]) { fa[v]=x; q[ta++]=v; if(n==v) return 1; } } } return 0; } void dfs(int dian,int depth)//求去掉最少个数点 { if(flag==false) return ; if(dian>depth) return ; int p=bfs(); int sa[N]={0},t=0; if(p==0){flag=false;return;} for(int i=n;i!=1;i=fa[i]) { sa[t++]=i; if(t>k){flag=false;return ;} } for(int i=1;i<t;i++) { int x=sa[i]; if(vis[x]) continue; vis[x]=1; dfs(dian+1,depth); vis[x]=0; if(flag==false) return ; } } void IDA() { if(n<=2) { puts("0"); return ; } int depth=0; flag=true; vis[1]=1; while(flag) { dfs(0,depth); if(!flag) break; depth++; } pi1(depth); } int main() { // freopen("input.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&k)&&(n+m+k)) { mset(lin,0); forb(i,0,m) { int a,b,t; si2(a,b); t=++lin[a][0]; lin[a][t]=b; //这个地方写双向的就WA了,单向的就A了 } IDA(); } return 0; }
超时代码:(IDA* + DFS)个人感觉应该差不多,但是就是超时了
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cstdlib> #include <cmath> #include <vector> #include <list> #include <deque> #include <queue> #include <iterator> #include <stack> #include <map> #include <set> #include <algorithm> #include <cctype> using namespace std; #define si1(a) scanf("%d",&a) #define si2(a,b) scanf("%d%d",&a,&b) #define sd1(a) scanf("%lf",&a) #define sd2(a,b) scanf("%lf%lf",&a,&b) #define ss1(s) scanf("%s",s) #define pi1(a) printf("%d\n",a) #define pi2(a,b) printf("%d %d\n",a,b) #define mset(a,b) memset(a,b,sizeof(a)) #define forb(i,a,b) for(int i=a;i<b;i++) #define ford(i,a,b) for(int i=a;i<=b;i++) typedef long long LL; const int N=1005; const int M=105; const int INF=0x3f3f3f3f; const double PI=acos(-1.0); const double eps=1e-7; int n,m,k; int lin[N][N];//邻接表储存 int cnt[M];//记录从1到n最短路径 bool vis[N];//标记节点是否被删除 int ans,Min; bool flag; struct xh { int x,y,next; }edge[N]; void dfs2(int k,int de)//求最短距离 { cnt[de]=k;//路径 if(k==n) { Min=min(Min,de); return ; } for(int i=1;i<=lin[k][0];i++) { int t=lin[k][i]; if(vis[t]) continue; vis[t]=1; dfs2(t,de+1); vis[t]=0; } } void dfs1(int dian,int depth)//求去掉最少个数点 { if(flag==false) return ; Min=INF; mset(cnt,0); dfs2(1,0); // cout<<"最短距离"<<Min<<endl; // cout<<"路径:"; // if(Min!=INF) // { // for(int i=0;i<=Min;i++) // printf("%d ",cnt[i]); // cout<<endl; // } // system("pause"); int xh=Min; if(xh>=k) { flag=false; ans=min(ans,dian); return ; } if(dian>=depth) return ; int sa[N]; for(int i=0;i<=xh;i++) sa[i]=cnt[i]; for(int i=1;i<xh;i++) { int t=sa[i]; if(vis[t]) continue; vis[t]=1; dfs1(dian+1,depth); vis[t]=0; if(flag==false) return ; } } int main() { // freopen("input.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&k)&&(n+m+k)) { mset(lin,0); forb(i,0,m) { int a,b,t; si2(a,b); t=++lin[a][0]; lin[a][t]=b; t=++lin[b][0]; lin[b][t]=a; } ans=INF; mset(vis,0); vis[1]=1; flag=true; int depth=-1; while(flag) { depth++; dfs1(0,depth); } pi1(depth); } return 0; }