构图很有趣,我是把区域当成构图的点,然后floyd+枚举每个区域到所有会员的穿过墙的和。求出。
开始wa是想错了一个地方。就是没看清题目给的区域点是按逆时针给出。。。然后竟然把一个区域的所有点都当成是可以连接的边了。。。囧。。其实很简单。。可是搞了很久。。
View Code
1 // File Name: 1161.cpp 2 // Author: Missa 3 // Created Time: 2013/2/2 星期六 13:46:13 4 5 #include<iostream> 6 #include<cstdio> 7 #include<cstring> 8 #include<algorithm> 9 #include<cmath> 10 #include<queue> 11 #include<stack> 12 #include<string> 13 #include<vector> 14 #include<cstdlib> 15 #include<map> 16 using namespace std; 17 18 const int maxn = 5e2+5; 19 const int inf = 0x3f3f3f3f; 20 int n,m,l; 21 int dis[maxn][maxn]; 22 int ds[maxn][maxn]; 23 bool mem[maxn]; 24 int tmp[maxn]; 25 int main() 26 { 27 while(~scanf("%d",&m)) 28 { 29 scanf("%d%d",&n,&l); 30 //memset(dis,0x7f,sizeof(dis)); 31 for(int i=0;i<maxn;i++) 32 for(int j=0;j<maxn;j++) 33 { 34 if(i==j) dis[i][j]=0; 35 else dis[i][j]=inf; 36 } 37 memset(mem,0,sizeof(mem)); 38 memset(ds,0,sizeof(ds)); 39 int x; 40 for(int i=0;i<l;i++) 41 { 42 scanf("%d",&x); 43 mem[x]=1; 44 } 45 for(int i=1;i<=m;i++) 46 { 47 scanf("%d",&x); 48 for(int j=0;j<x;j++) 49 { 50 scanf("%d",&tmp[j]); 51 if(mem[tmp[j]]) 52 dis[m+tmp[j]][i]=dis[i][m+tmp[j]]=0; 53 } 54 tmp[x]=tmp[0]; 55 for(int k=0;k<x;k++) 56 { 57 int tt=ds[tmp[k]][tmp[k+1]]; 58 if(tt==0) 59 ds[tmp[k]][tmp[k+1]]=ds[tmp[k+1]][tmp[k]]=i; 60 else 61 dis[i][tt]=dis[tt][i]=1; 62 } 63 } 64 for(int k=1;k<=m;k++) 65 for(int i=1;i<=m;i++) 66 for(int j=1;j<=m;j++) 67 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 68 for(int i=1;i<=m;i++) 69 { 70 for(int j=1;j<=n;j++) 71 { 72 if(mem[j] && dis[i][m+j]==0) 73 { 74 for(int k=1;k<=m;k++) 75 { 76 if(dis[m+j][k]>dis[i][k]) 77 dis[m+j][k]=dis[k][m+j]=dis[i][k]; 78 } 79 } 80 } 81 } 82 int ans=inf; 83 int tt=0; 84 for(int i=1;i<=m;i++) 85 { 86 tt=0; 87 for(int j=1;j<=n;j++) 88 { 89 if(mem[j]) 90 { 91 tt+=dis[i][m+j]; 92 // cout<<"dis:"<<i<<" "<<j<<" ="<<dis[i][m+j]<<endl; 93 } 94 } 95 if(tt<ans) 96 ans=tt; 97 //cout<<"区域:"<<i<<" tmp="<<tmp<<endl; 98 } 99 printf("%d\n",ans); 100 } 101 return 0; 102 }