• POJ 2195 Going Home 最小费用流 裸题


    给出一个n*m的图,其中m是人,H是房子,.是空地,满足人的个数等于房子数。

    现在让每个人都选择一个房子住,每个人只能住一间,每一间只能住一个人。

    每个人可以向4个方向移动,每移动一步需要1$,问所有人移动到房子里的最少花费。

    其中,n,m<=100,最多有100个人。

    最小给用流裸题。

    建立一个超级源点,跟每一个房子连一条边,容量为1,花费为0

    每一个人与超级汇点连一条边,容量为1,花费为0

    一个房子与每一个人建一条边,房子指向人,容量为1,花费用2者的距离(不是直线距离)

    然后跑最小费用流算法就可以了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<queue>
      5 
      6 using namespace std;
      7 
      8 const int maxn=205;
      9 const int inf=0x3f3f3f3f;
     10 const int s=0;
     11 int t;
     12 int tot;
     13 char maze[maxn];
     14 char str[maxn][maxn];
     15 bool vis[maxn];
     16 int dis[maxn];
     17 int prev[maxn];
     18 int pree[maxn];
     19 
     20 struct Point
     21 {
     22     int x,y;
     23 };
     24 Point point[maxn];
     25 struct Edge
     26 {
     27     int to,cap,cost,rev;
     28 };
     29 vector<Edge>edge[maxn];
     30 
     31 inline int get_abs(int tmp)
     32 {
     33     if(tmp>0)
     34         return tmp;
     35     return -tmp;
     36 }
     37 
     38 inline int min(int x,int y)
     39 {
     40     return x<y?x:y;
     41 }
     42 
     43 inline int get_dis(int i,int j)
     44 {
     45     return get_abs(point[i].x-point[j].x)+get_abs(point[i].y-point[j].y);
     46 }
     47 
     48 void addedge(int from,int to,int cap,int cost)
     49 {
     50     edge[from].push_back((Edge){to,cap,cost,edge[to].size()});
     51     edge[to].push_back((Edge){from,0,-cost,edge[from].size()-1});
     52 }
     53 
     54 void build_graph(int n,int m)
     55 {
     56     //要从0开始
     57     for(int i=0;i<maxn;i++)
     58         edge[i].clear();
     59     tot=1;
     60     for(int i=1;i<=n;i++)
     61     {
     62         for(int j=1;j<=m;j++)
     63         {
     64             if(str[i][j]=='H')
     65             {
     66                 point[tot].x=i;
     67                 point[tot++].y=j;
     68             }
     69         }
     70     }
     71     for(int i=1;i<=n;i++)
     72     {
     73         for(int j=1;j<=m;j++)
     74         {
     75             if(str[i][j]=='m')
     76             {
     77                 point[tot].x=i;
     78                 point[tot++].y=j;
     79             }
     80         }
     81     }
     82     t=tot;
     83     tot--;
     84     tot/=2;
     85     for(int i=1;i<=tot;i++)
     86     {
     87         addedge(s,i,1,0);
     88         addedge(i+tot,t,1,0);
     89     }
     90     for(int i=1;i<=tot;i++)
     91     {
     92         for(int j=tot+1;j<=tot*2;j++)
     93         {
     94             addedge(i,j,1,get_dis(i,j));
     95         }
     96     }
     97 }
     98 
     99 void spfa()
    100 {
    101     memset(vis,false,sizeof vis);
    102     for(int i=0;i<=t;i++)
    103         dis[i]=inf;
    104     queue<int>que;
    105     while(!que.empty())
    106         que.pop();
    107     que.push(s);
    108     dis[s]=0;
    109     vis[s]=true;
    110     while(!que.empty())
    111     {
    112         int u=que.front();
    113         que.pop();
    114         vis[u]=false;   //要记得这步
    115         for(int i=0;i<edge[u].size();i++)
    116         {
    117             Edge &e=edge[u][i];
    118             if(e.cap>0&&dis[e.to]>dis[u]+e.cost)
    119             {
    120                 dis[e.to]=dis[u]+e.cost;
    121                 prev[e.to]=u;
    122                 pree[e.to]=i;
    123                 if(!vis[e.to])
    124                 {
    125                     vis[e.to]=true;
    126                     que.push(e.to);
    127                 }
    128             }
    129         }
    130     }
    131     return ;
    132 }
    133 
    134 int solve()
    135 {
    136     int ret=0;
    137     int flow=tot;
    138     while(flow>0)
    139     {
    140         spfa();
    141         int f=flow;
    142         for(int i=t;i!=s;i=prev[i])
    143         {
    144             f=min(f,edge[prev[i]][pree[i]].cap);
    145         }
    146         flow-=f;
    147         ret+=dis[t]*f;
    148         for(int i=t;i!=s;i=prev[i])
    149         {
    150             Edge &e=edge[prev[i]][pree[i]];
    151             e.cap-=f;
    152             edge[e.to][e.rev].cap+=f;
    153         }
    154     }
    155     return ret;
    156 }
    157 
    158 int main()
    159 {
    160     int n,m;
    161     while(~scanf("%d%d",&n,&m))
    162     {
    163         if(!n&&!m)
    164             break;
    165         for(int i=1;i<=n;i++)
    166         {
    167             scanf("%s",str[i]+1);
    168         }
    169         build_graph(n,m);
    170         printf("%d
    ",solve());
    171     }
    172     return 0;
    173 }
    View Code
  • 相关阅读:
    Java中swing常用控件背景设置透明的方法
    SpringMVC工作原理
    关于spring框架工作原理
    Java-JFrame窗体美化方式
    Java swing GUI窗口美化
    Java-Swing是什么?
    SSM+Redis+Layui前端框架实现验证码的发送
    SSM+Redis+Layui实现注册功能
    SSM+Layui实现模拟登录功能
    SSM+layui分页(了解98%)
  • 原文地址:https://www.cnblogs.com/-maybe/p/4714409.html
Copyright © 2020-2023  润新知