zoukankan      html  css  js  c++  java
  • POJ 2195 Going Home 最小费用流

     POJ2195

    裸的最小费用流,当然也可以用KM算法解决,但是比较难写。

    注意反向边的距离为正向边的相反数(因此要用SPFA)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=302,src=301,sink=300,INF=1e+8; 
    int n,m,man,house,x[maxn],y[maxn],cap[maxn][maxn],w[maxn][maxn];
    vector<int> next[maxn];
    
    
    void addedge(int a,int b)
    {
     next[a].push_back(b);next[b].push_back(a);
     cap[a][b]=1;cap[b][a]=0;
    }
    
    int ab(int xx)
    {
     if(xx<0)return xx*(-1);
     	else return xx;
    }
    int fa[maxn];
    int len(int a,int b)
    {
     if((a==src)||(a==sink)||(b==src)||(b==sink))return 0;
     return ab(x[b]-x[a])+ab(y[b]-y[a]);
    }
    bool inq[maxn];
    int times[maxn],dist[maxn];
    bool SPFA()
    {
     
     memset(inq,0,sizeof(inq));
     for(int i=0;i<maxn;i++)
     	dist[i]=INF;
     dist[src]=0;
     queue<int>q;
     q.push(src);
     inq[src]=true;
     while(!q.empty())
     	{
     	 int now=q.front(); 
    	 q.pop();
    	 inq[now]=false;
    	 for(int i=0;i<next[now].size();i++)
    	 	{
    	 	 int np=next[now][i];
    	 	 if((dist[np]>dist[now]+w[now][np])&&cap[now][np]>0)
    	 	 	{
    	 	 	 dist[np]=dist[now]+w[now][np];
    	 	 	 fa[np]=now;
    	 	 	 if(!inq[np]){q.push(np);inq[np]=true;}
    			}
    		}	
    	}
     if( dist[sink]<INF)return true;
     	else return false;
    }
    
    int augment()
    
    {
     int u=sink,delta=INF;
     while(u!=src)
     	{
     	 if(cap[fa[u]][u]<delta)delta=cap[fa[u]][u];
     	 u=fa[u];
    	} 
     u=sink;
     while(u!=src)
     	{
     	 cap[fa[u]][u]-=delta;
     	 cap[u][fa[u]]+=delta;
     	 u=fa[u];
    	}
     return  dist[sink]*delta;
    }
    
    int main()
    {ios::sync_with_stdio(false);
     while(cin>>n>>m)
     	{
     	 if(n==0&&m==0)return 0;
     	 man=0;house=150;
     	 memset(cap,0,sizeof(cap));memset(w,0,sizeof(w));
     	 for(int i=0;i<maxn;i++)
     	 	while(next[i].size()>0)next[i].pop_back();
     	 for(int i=0;i<n;i++)
     	 	{    
     	        
    	  		for(int j=0;j<m;j++)
     	    		{
     	    		 char c;
     	    		 cin>>c;
     	    		 if(c=='m')
     	    		 	{
     	    		 	  x[man]=i;y[man]=j;
     	    		 	  man++;
    					}
     	             if(c=='H')
     	             	{
     	             	  x[house]=i;y[house]=j;
     	             	  house++;
    					}
    				}
    		}
    	 for(int i=150;i<house;i++)
    	 	{
    	 	 addedge(i,sink);
    	 	 for(int j=0;j<man;j++)
    	 	 	addedge(j,i);
    		}
    	 for(int j=0;j<man;j++) addedge(src,j);
    	 int ans=0;
    	 for(int i=0;i<man;i++)
    	 	for(int j=150;j<house;j++)
    	 		{
    	 		 w[i][j]=len(i,j);
    	 		 w[j][i]=w[i][j]*(-1);
    			}
     	 while(SPFA())
     		{
    	 	 ans+=augment();
    		}
    	 cout<<ans<<endl;
    	}
     
     
     return 0;
    }
    

      

    ,没什么别的了,很简单。

  • 相关阅读:
    14、Cahin of Responsibility 责任链 COR设计模式
    13、Visitor 访问者模式 访问数据结构并处理数据 行为型设计模式
    HTML inline 与block元素
    javascript 继承实现
    深入理解linux的权限设置和SUID,SGID以及粘滞位
    设置express ejs模板的后缀名html
    Centos 安装编译codeblocks&&codelite
    JavaScript中两种类型的全局对象/函数【转】
    Canvas vs. SVG[转]
    centos 学习总结
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6442095.html
Copyright © 2011-2022 走看看