题意:给出一个有向图,起点为0,终点为m,求删去一个最靠近m且不是m的点,使得0不能到m。
题解:dijiskra求一遍反向最短路,然后枚举所有dist<ans的点,删去它后0还能否到m。
View Code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int N=10000; 6 int head[N],dist[N],nc,_nc,_head[N]; 7 struct Edge 8 { 9 int to,next; 10 } edge[N*100],_edge[N*100]; 11 void add(int a,int b) 12 { 13 edge[nc].to=b; 14 edge[nc].next=head[a]; 15 head[a]=nc++; 16 } 17 void addf(int a,int b) 18 { 19 _edge[_nc].to=b; 20 _edge[_nc].next=_head[a]; 21 _head[a]=_nc++; 22 } 23 bool vis[N]; 24 int T; 25 void diji(int n) 26 { 27 memset(dist,-1,sizeof(dist)); 28 dist[T]=0; 29 memset(vis,false,sizeof(vis)); 30 for(int i=0;i<n;i++) 31 { 32 int k=-1,mmin=1<<30; 33 for(int j=0;j<n;j++) 34 if(!vis[j]&&dist[j]!=-1&&mmin>dist[j]) 35 mmin=dist[k=j]; 36 if(k==-1) 37 return; 38 vis[k]=true; 39 for(int j=_head[k];j!=-1;j=_edge[j].next) 40 { 41 int t=_edge[j].to; 42 if(dist[t]==-1||dist[t]>dist[k]+1) 43 dist[t]=dist[k]+1; 44 } 45 } 46 } 47 bool check(int now) 48 { 49 vis[now]=true; 50 if(now==T) 51 return true; 52 for(int i=head[now];i!=-1;i=edge[i].next) 53 { 54 if(!vis[edge[i].to]) 55 { 56 if(check(edge[i].to)) 57 return true; 58 } 59 } 60 return false; 61 } 62 int main() 63 { 64 int n,a,b; 65 scanf("%d%d",&n,&T); 66 memset(head,-1,sizeof(head)); 67 memset(_head,-1,sizeof(_head)); 68 nc=_nc=0; 69 while(scanf("%d%d",&a,&b)!=EOF) 70 add(a,b),addf(b,a); 71 diji(n); 72 int ans=0; 73 for(int i=1; i<n; i++) 74 { 75 if(i!=T&&dist[i]!=-1&&dist[i]<dist[ans]) 76 { 77 memset(vis,false,sizeof(vis)); 78 vis[i]=true; 79 if(!check(0)) 80 ans=i; 81 } 82 } 83 printf("Put guards in room %d.\n",ans); 84 return 0; 85 }