题目
Network 公司的BOSS 说现在他们公司建立的信号发射站和接收站经常出现信号发送接收不稳定的问题,信号的稳定度被定义为发射点到接收点的距离,距离越大,越不稳定,所以发射点跟接收点在可能的情况下应越近越好.
BOSS给8600的任务就是::建立一个匹配表,使得一个发射点对应一个接收点,对于某一个发射点来说,它的接收点离它越近那么就会更稳定,同样对于接收点也是一样的情况. 匹配的目标是使得整个网络变得稳定。,对于某2个匹配,比如,( a ---- 1) ,(b----2) ,如果发射点a 离接收点2 比 1要近,而且2 也离 发射点a要比 b 近, 那么 a 就很有可能把信号发到 2中,我们就说这个搭配是不 稳定的。同样如果发射点b 离接收点1 比 2 要近,而且1 也离 发射点b要比 a 近 ,也会出现不稳定的情 况. 而且每个点都有一个容量值,如果对于一个发射点到2个接收点的距离一样的话,它将首先选择容量大的那个. 所以8600就是要建立一个稳定的匹配,使得每个一个信号发射点对应一个接收点,并且不会出现信号不稳定的情况.
8600苦思冥想也没什么进展,希望你能帮他解决这个难题.
Input
输入数据首先包含一个正整数N,N<=20表示测试实例的个数.每个实例首先是一个整C,C<=200表示有C个信号发射点和C个信号接收点. 接下来的C行表示 C个发射点的编号,容量和坐标,坐标为,x,y,z 3个实数(x,y,z ≥0).最后C行是C个接收点的编号,容量和坐标.
Output
输出建立稳定搭配后各个发射点和接收点的编号,每一行代表一个搭配,前一个整数为发射点的编号,后一个为对应的接收点的编号。如果有多种情况,输出其中一种即可.如果任务不可能完成的话,输出"Impossible".每个实例后请输出一个空行.
Sample Input
1
3
1 1 60.57 57.16 69.27
2 2 26.05 61.06 11.52
3 3 9.04 58.20 56.90
1 2 280.74 12.78 316.14
2 3 305.16 267.15 87.65
3 1 240.72 312.41 217.10
Sample Output
3 1
1 2
2 3
思路
稳定婚姻裸题。这里简单说一下这个算法。稳定婚姻算法,又叫渣男不要脸找对象算法(hhha),大概的意思就是,我又一个二分图,然后左部每个点对于右部的点都有一个各自的期望值,右部也是一样,我们可以理解为男生追女生,道理是一样,想象一下,一对男女结婚了,但是这两个男女在外面都有更加好的外遇,那么他们就可以break up然后找外面的情人去了,何乐而不为呢,那么我们说这种情况是不稳定的婚姻,也就是易于拆散的。解决这个问题的算法叫做GS算法,我们对于所有男生列一个对女生的喜好度排行,女生也一样。我们从男生开始找,如果女生没有男朋友,那就暂时在一起,然后换下一个男生追女孩子,同样贪心的追最希望在一起的,如果女生没有男朋友,在一起,如果有,那么看看男朋友和追自己的哪个好,如果优于目前对象,果断踹掉,这现在这个在一起。一直这样一直到所有男生都有对象为止。关于这个正确性的证明,简单想一下,女生选择的一定是追自己的最优的,男生选择的一定是自己可以追到的最优的,所以最后构成的就是一个稳定婚姻的局面。
代码实现
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=0;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005
#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef pair<int ,int> PII;
ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
const int maxn=200+5;
struct point {
int c;
double x,y,z;
};
struct node {
double dis;
int pos;
int c,l;
};
int t,n;
int women[maxn],man[maxn];
int ranks[maxn][maxn],ranke[maxn][maxn];
node rank[maxn];
int tempman[maxn];
point S[maxn],E[maxn];
bool cmp (node a ,node b) {
if (abs (a.dis-b.dis)<=exp) {
return a.c<b.c;
}
else return a.dis<b.dis;
}
bool cmp2 (node a,node b) {
return a.l<b.l;
}
double get_dis (point a,point b) {
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z);
}
inline void countrank () {
rep (i,1,n) {
MT (rank,0);
rep (j,1,n) {
rank[j].pos=j;
rank[j].dis=get_dis (S[i],E[j]);
rank[j].c=E[j].c;
}
sort (rank+1,rank+1+n,cmp);
rep (j,1,n) {
ranks[i][j]=rank[j].pos;
}
}
rep (i,1,n) {
MT (rank,0);
rep (j,1,n) {
rank[j].pos=j;
rank[j].dis=get_dis (E[i],S[i]);
rank[j].c=S[j].c;
}
sort (rank+1,rank+1+n,cmp);
rep (j,1,n) {
rank[j].l=j;
}
sort (rank+1,rank+1+n,cmp2);
rep (j,1,n) {
ranke[i][j]=rank[j].l;
}
}
}
inline void input () {
int a,b;
double c,d,e;
cin>>n;
rep (i,1,n) {
cin>>a>>b>>c>>d>>e;
S[i].c=b;
S[i].x=c;
S[i].y=d;
S[i].z=e;
}
rep (i,1,n) {
cin>>a>>b>>c>>d>>e;
E[i].c=b;
E[i].x=c;
E[i].y=d;
E[i].z=e;
}
rep (i,1,n) tempman[i]=1;
}
inline void GS () {
int flag=1;
MT (women,0);
MT (man,0);
while (flag==1) {
flag=0;
rep (i,1,n) {
if (man[i]==0) {
flag=1;
int womenpos=ranks[i][tempman[i]];
if (women[womenpos]==0) {
women[womenpos]=i;
man[i]=womenpos;
tempman[i]++;
}
else if (ranke[womenpos][women[womenpos]]>ranke[womenpos][i]) {
man[women[womenpos]]=0;
women[womenpos]=i;
man[i]=womenpos;
tempman[i]++;
}
else tempman[i]++;
}
}
}
}
int main () {
cin>>t;
while (t--) {
input ();
countrank ();
GS ();
rep (i,1,n) printf ("%d %d
",women[i],i);
}
return 0;
}