傳送門: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;}