hdu2255 奔小康赚大钱
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255
#include<cstdio>
#include<cstring>
using namespace std;
const int N=310;
const int inf=0x3f3f3f3f;
int nx,ny;
int g[N][N];//权值
int linker[N],lx[N],ly[N];//linker[i]=表示集合y中j与x中i匹配
int slack[N];//记录过程中的d
bool visx[N],visy[N];
bool DFS(int x)
{
visx[x]=true;
for(int y=0;y<ny;y++)
{
if(visy[y]) continue;
int tmp=lx[x]+ly[y]-g[x][y];
if(tmp==0)
{
visy[y]=true;
if(linker[y]==-1||DFS(linker[y]))
{
linker[y]=x;
return true;
}
}
else if(slack[y]>tmp)
slack[y]=tmp;
}
return false;
}
int km()
{
memset(linker,-1,sizeof(linker));
memset(ly,0,sizeof(ly));
for(int i=0;i<nx;i++)
{
lx[i]=-inf;
for(int j=0;j<ny;j++)
if(g[i][j]>lx[i])
lx[i]=g[i][j];
} //初始化使lx[x]里存最大的权值;
for(int x=0;x<nx;x++)
{
for(int i=0;i<ny;i++)
slack[i]=inf;
while(true)
{
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
if(DFS(x)) break;
int d=inf;
for(int i=0;i<ny;i++)
if(!visy[i]&&d>slack[i])
d=slack[i];
for(int i=0;i<nx;i++)
if(visx[i])
lx[i]-=d;
for(int i=0;i<ny;i++)
{
if(visy[i]) ly[i]+=d;
else slack[i]-=d;
}
}
}
int res=0;
for(int i=0;i<ny;i++)
if(linker[i]!=-1)
res+=g[linker[i]][i];
return res;
}
int main()
{
int n,i,j;
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&g[i][j]);
nx=ny=n;
printf("%d\n",km());
}
return 0;
}
poj3565 Ants
题目链接:http://poj.org/problem?id=3565
思路:最小权值的匹配,把距离取相反数,即可以套km的模板啦,注意double;
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int num=105;
const int inf=0x3f3f3f3f;
struct node
{
int x,y;
}dx[num],dy[num];
int nx,ny;
double g[num][num],lx[num],ly[num],slack[num];
int linker[num];
bool visx[num],visy[num];
double qd(int a,int b)
{
double tx,ty;
tx=dx[a].x-dy[b].x;
ty=dx[a].y-dy[b].y;
return sqrt(tx*tx+ty*ty);
}
bool dfs(int x)
{
visx[x]=true;
for(int y=0;y<ny;y++)
{
if(visy[y]) continue;
double tmp=lx[x]+ly[y]-g[x][y];
if(abs(tmp)<1e-10)
{
visy[y]=true;
if(linker[y]==-1||dfs(linker[y]))
{
linker[y]=x;
return true;
}
}
else if(slack[y]>tmp)
slack[y]=tmp;
}
return false;
}
double km()
{
memset(linker,-1,sizeof(linker));
for(int i=0;i<ny;i++)
ly[i]=0.0;
for(int i=0;i<nx;i++)
{
lx[i]=-inf;
for(int j=0;j<ny;j++)
if(g[i][j]>lx[i])
lx[i]=g[i][j];
}
for(int x=0;x<nx;x++)
{
for(int i=0;i<ny;i++)
slack[i]=inf;
while(true)
{
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
if(dfs(x))break;
double d=inf;
for(int i=0;i<ny;i++)
if(!visy[i]&&d>slack[i])
d=slack[i];
for(int i=0;i<nx;i++)
if(visx[i])
lx[i]-=d;
for(int i=0;i<ny;i++)
{
if(visy[i])ly[i]+=d;
else slack[i]-=d;
}
}
}
return 0.0;
}
int main()
{
int n,i,j,ans[num];
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
scanf("%d%d",&dx[i].x,&dx[i].y);
for(i=0;i<n;i++)
scanf("%d%d",&dy[i].x,&dy[i].y);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
g[i][j]=-qd(i,j);
nx=ny=n;
km();
for(i=0;i<n;i++)
ans[linker[i]]=i;
for(i=0;i<n;i++)
printf("%d\n",ans[i]+1);
}
return 0;
}