【spfa】bzoj1295 [SCOI2009]最长距离
题意:给你一个n*m的点阵、有些点是障碍,求一个欧几里得距离最大的点对(A,B),使得在移走的障碍≤T的情况下,可以从A走到B。
建图,跑n*m次spfa,求出从 每个点 出发到 其他所有点 的 经过的障碍数。若这个值<=T,则可以用来更新答案。
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int dx[]={0,0,1,-1},dy[]={1,-1,0,0}; 8 queue<int>q; 9 char map[31][31]; 10 int n,en,m,K,first[50001],next[50001],v[50001],w[50001],dis[50001],num[31][31]; 11 bool inq[50001]; 12 double ans; 13 void init(const int &s) 14 {memset(dis,0x7f,sizeof(dis)); inq[s]=true; dis[s]=0; q.push(s);} 15 void AddEdge(const int &U,const int &V,const int &W) 16 {v[++en]=V; w[en]=W; next[en]=first[U]; first[U]=en;} 17 int sqr(const int &x){return x*x;} 18 double Euclid_Dis(const int &x1,const int &y1,const int &x2,const int &y2) 19 {return sqrt(sqr(x1-x2)+sqr(y1-y2));} 20 void spfa(const int &s) 21 { 22 init(s); 23 while(!q.empty()) 24 { 25 int cur=q.front(); 26 for(int i=first[cur];i;i=next[i]) 27 if(dis[v[i]]>dis[cur]+w[i]) 28 { 29 dis[v[i]]=dis[cur]+w[i]; 30 if(!inq[v[i]]) 31 { 32 q.push(v[i]); 33 inq[v[i]]=true; 34 } 35 } 36 q.pop(); inq[cur]=false; 37 } 38 } 39 void calc(const int &x,const int &y) 40 { 41 K-=(map[x][y]=='1'); 42 for(int i=0;i<n;i++) 43 for(int j=0;j<m;j++) 44 if(dis[num[i][j]]<=K) 45 ans=max(ans,Euclid_Dis(x,y,i,j)); 46 K+=(map[x][y]=='1'); 47 } 48 void BuildGraph() 49 { 50 for(int i=0;i<n;i++) 51 for(int j=0;j<m;j++) 52 for(int k=0;k<4;k++) 53 { 54 int tx=i+dx[k],ty=j+dy[k]; 55 if(tx>=0&&tx<n&&ty>=0&&ty<n) 56 if(map[tx][ty]=='1') AddEdge(num[i][j],num[tx][ty],1); 57 else AddEdge(num[i][j],num[tx][ty],0); 58 } 59 } 60 int main() 61 { 62 scanf("%d%d%d",&n,&m,&K); 63 for(int i=0;i<n;i++) 64 scanf("%s",map[i]); 65 for(int i=0;i<n;i++) 66 for(int j=0;j<m;j++) 67 num[i][j]=++en; 68 en=0; 69 BuildGraph(); 70 for(int i=0;i<n;i++) 71 for(int j=0;j<m;j++) 72 { 73 spfa(num[i][j]); 74 calc(i,j); 75 } 76 printf("%.6lf\n",ans); 77 return 0; 78 }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/