poj 1161 walls

构图很有趣,我是把区域当成构图的点,然后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 }

 

转载于:https://www.cnblogs.com/Missa/archive/2013/02/02/2890512.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值