分治法解法:
感觉能用分治法解的问题都有自相似性吧。
就是说把大的情况按某种方式切成几个小的情况,这些小的情况和大的情况是相似的。
如果满足这个条件,那么最简单的情况的解答方案是显然的。
我们只需要考虑好如何合并多个小情况即可。
跟快速排序的思想很像啊。
看紫书P227吧,讲的详细。
最小权完美匹配解法:
黑点和白点个数相同,每个黑点要找一个白点,应该要想到二分图完美匹配。
二分图匹配的算法与模板就这么几个。
唯一能当边权的东西也就是距离了。
思考一下,一个个试试,也就差不多出来了。
要求不相交,则为距离的最小权匹配。还是比较机智的。
用最小费最大流求最小权完美匹配,完美匹配一定存在。
做的时候犯了个小错误,搞了好几个小时。
当时觉得把模板里ll改成double很麻烦,ll范围也够,反正都是找最短路,开不开方不影响距离大小的比较。
事实上改double很快的,分分钟改完而且不开方是错的。原因在于反向增广时会对距离进行求和,显然平方求和会降低短边的权重,增加长边的权重,导致找出来的最短路是错的。如
黑1
黑2 白1
白2
若第一次找最短路时(第一次肯定不会反向增广)找了白1连黑2。
若用平方,则发现交叉的情况距离短,因此会沿着错误的路径增广。
不用则会得到正确的结果。
附上两份代码
第一份分治法
第二份用最小费最大流求最小权完美匹配
#include
#include
#define maxn 210
using namespace std;
struct Node
{
int x,y;
bool id;
int bianhao;
};
Node node[maxn];
Node ji;
bool cmp1(Node& a,Node& b)
{
if(a.y!=b.y) return a.yr) return;
sort(node+l,node+r+1,cmp1);
ji=node[l];
sort(node+l+1,node+r+1,cmp2);
int cnt1=0,cnt2=0;
int k=r;
while(!(ji.id!=node[k].id&&cnt1==cnt2))
{
if(node[k].id==ji.id) cnt1++;
else cnt2++;
k--;
}
if(ji.id) ans[node[k].bianhao]=ji.bianhao;
else ans[ji.bianhao]=node[k].bianhao;
dfs(l+1,k-1);
dfs(k+1,r);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d %d",&node[i].x,&node[i].y);
node[i].id=false;
node[i].bianhao=i;
}
for(int i=n+1;i<=2*n;i++)
{
scanf("%d %d",&node[i].x,&node[i].y);
node[i].id=true;
node[i].bianhao=i-n;;
}
dfs(1,2*n);
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}
return 0;
}
#include
#include
#include
#include
#include
#include
#define maxn 210
using namespace std;
double const INF=numeric_limits::max();
struct Edge
{
int from,to,cap,flow;
double cost;
Edge(int u,int v,int c,int f,double w):from(u),to(v),cap(c),flow(f),cost(w){}
};
struct MCMF
{
int n,m;
vectoredges;
vectorG[maxn];
int inq[maxn];
double d[maxn];
int p[maxn];
int a[maxn];
void init(int n)
{
this->n=n;
for(int i=0;iQ;
Q.push(s);
while(!Q.empty())
{
int u=Q.front();Q.pop();
inq[u]=0;
for(unsigned int i=0;ie.flow&&d[e.to]>d[u]+e.cost)
{
d[e.to]=d[u]+e.cost;
p[e.to]=G[u][i];
a[e.to]=min(a[u],e.cap-e.flow);
if(!inq[e.to]){Q.push(e.to);inq[e.to]=1;}
}
}
}
if(d[t]==INF) return false;
flow+=a[t];
cost+=d[t]*a[t];
for(int u=t;u!=s;u=edges[p[u]].from)
{
edges[p[u]].flow+=a[t];
edges[p[u]^1].flow-=a[t];
}
return true;
}
int MincostMaxflow(int s,int t,double& cost)
{
int flow=0;cost=0;
while(BellmanFord(s,t,flow,cost));
return flow;
}
};
struct Node
{
double x,y;
};
Node node1[maxn];
Node node2[maxn];
double dist(int i,int j)
{
double xx=node1[i].x-node2[j].x;
double yy=node1[i].y-node2[j].y;
return sqrt(xx*xx+yy*yy);
}
int n;
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%lf %lf",&node1[i].x,&node1[i].y);
for(int i=1;i<=n;i++)
scanf("%lf %lf",&node2[i].x,&node2[i].y);
MCMF mcmf;
mcmf.init(2*n+2);
for(int i=1;i<=n;i++)
{
mcmf.AddEdge(0,i,1,0);
mcmf.AddEdge(i+n,2*n+1,1,0);
for(int j=1;j<=n;j++)
mcmf.AddEdge(i,j+n,1,dist(i,j));
}
double cost;
mcmf.MincostMaxflow(0,2*n+1,cost);
for(int i=1;i<=n;i++)
for(unsigned int j=0;j=n+1&&e.to<=2*n)
{
printf("%d\n",e.to-n);
break;
}
}
}
return 0;
}