hdu 2255 km入门题

来源:互联网 发布:淘宝卖家寄寿衣怎么办 编辑:程序博客网 时间:2024/05/18 13:46
#include<stdio.h>  #include<string.h>  #include<stdlib.h>  #define N 305  #define inf 0x3fffffff  int n,map[N][N],lx[N],ly[N],match[N];  bool s[N],t[N];//s[]、t[]为左/右第i个点是否在匈牙利树中int min(int a,int b)  {      if(a>b)return b;      return a; }  int max(int a,int b)  {      if(a>b)return a;      return b;  }  bool find(int u)//匈牙利,匹配(找增广路)  {      int i;       s[u]=true;      for(i=1;i<=n;i++)      {          if(!t[i]&&lx[u]+ly[i]==map[u][i])          {              t[i]=true;              if(match[i]==-1||find(match[i]))              {                  match[i]=u;//u跟i匹配                 return true;              }          }      }      return false;  }  int KM()  {      int ans=0;      memset(match,-1,sizeof(match));      memset(lx,0,sizeof(lx));      memset(ly,0,sizeof(ly));      for(int i=1;i<=n;i++)          for(int j=1;j<=n;j++)             lx[i]=max(lx[i],map[i][j]);//初始化S顶标为最大权           for(i=1;i<=n;i++)//匹配每一个点            {              while(1)              {                  memset(s,false,sizeof(s));                  memset(t,false,sizeof(t));                  if(find(i))break;//匹配成功                  else//匹配失败,找最小值                  {                      int a=inf;                      for(int j=1;j<=n;j++)                          if(s[j])//j在匈牙利树中                         {                              for(int k=1;k<=n;k++)                                  if(!t[k])//k在匈牙利树外                                      a=min(a,lx[j]+ly[k]-map[j][k]);//顶标修改量,使得权值减小最小                          }                          for(j=1;j<=n;j++)//修改顶标                          {                              if(s[j])lx[j]-=a;//保证至少有一条边可以加入                             if(t[j])ly[j]+=a;//保证原来匹配的边修改后依然可以匹配                          }                  }              }          }          for(i=1;i<=n;i++)//权值相加               ans+=map[match[i]][i];          return ans;  }                 int main()  {      int i,j;      while(scanf("%d",&n)!=-1)      {          for(i=1;i<=n;i++)              for(j=1;j<=n;j++)                  scanf("%d",&map[i][j]);              printf("%d\n",KM());      }      return 0;  }  

0 0
原创粉丝点击