POJ 1269(直线的交点)

Language:
Intersecting Lines
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 7657   Accepted: 3510

Description

求两条直线相交部分,给出的坐标的范围在 -1000 到 1000 之间且为整数. 

Input

第一行为数据组数 N≤10 
接下来N行,每行为x1y1x2y2x3y3x4y4.表示第一条直线过 (x1,y1) 和 (x2,y2) ,第二条过 (x3,y3) 和 (x4,y4). 保证直线能被确定.

Output

输出 N+2 第一行输出INTERSECTING LINES OUTPUT. 接下来每行输出相交部分 none, line, 或 point x y(保留2位小数). 最后1行输出 "END OF OUTPUT".

Sample Input

5
0 0 4 4 0 4 4 0
5 0 7 6 1 0 2 3
5 0 7 6 3 -6 4 -3
2 0 2 27 1 5 18 5
0 3 4 0 1 2 2 5

Sample Output

INTERSECTING LINES OUTPUT
POINT 2.00 2.00
NONE
LINE
POINT 2.00 5.00
POINT 1.07 2.20
END OF OUTPUT

Source

模板如下:

注意* 表示叉积

这题涉及已知相交,线段跨立求交点

异侧情况:


同侧情况:




#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define eps 1e-8
double sqr(double x) {return x*x;}
struct P
{
	double x,y;
	P(double _x,double _y):x(_x),y(_y){}
	P(){}
	double dis()
	{
		return sqrt(sqr(x)+sqr(y));
	}
};
struct V
{
	double x,y;
	V(double _x,double _y):x(_x),y(_y){}
	V(P a,P b):x(b.x-a.x),y(b.y-a.y){}
	V(){}
	const double dis()
	{
		return sqrt(sqr(x)+sqr(y));
	}
};
P operator+(const P a,const V b)
{
	return P(a.x+b.x,a.y+b.y);
}
V operator*(const double a,const V b)
{
	return V(a*b.x,a*b.y);
}
double operator*(const V a,const V b)
{
	return a.x*b.y-b.x*a.y;
}
P jiao_dian(const V a,V b,const V c,const V CD,const P C)
{
	double d;
	d=b.dis();
	double s1=a*b,s2=b*c;
	double k=s1/(s1+s2);
	return C+k*CD;
}
bool equal(const double a,const double b)
{
	if (abs(a-b)<eps) return 1;return 0;
}
int n;
int main()
{
//s	freopen("poj1269.in","r",stdin);
	cout<<"INTERSECTING LINES OUTPUT"<<endl;
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		double x1,y1,x2,y2,x3,y3,x4,y4;
		scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
		P A=P(x1,y1),B=P(x2,y2),C=P(x3,y3),D=P(x4,y4);
		V AB=V(A,B),AC=V(A,C),AD=V(A,D),CD=V(C,D);
		if (equal((AB*CD),0))
		{
			if (equal((AC*AD),0)) cout<<"LINEn";
			else cout<<"NONEn";
		}
		else
		{
			P p=jiao_dian(AC,AB,AD,CD,C);
			cout.setf(ios::fixed);
			cout.precision(2);
			cout<<"POINT "<<p.x<<' '<<p.y<<endl;
		}
	}
	cout<<"END OF OUTPUT"<<endl;
	return 0;
}

CF 254E(从当前向后递推)

E. 宿舍分享
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

一个学期有 n 天.第i天早上Vasya会带 ai kg食物来学校(食物最多放2天,今天和明天).

Vasya 每天吃 v kg 食物.他带来的食物原来够吃,但是Vasya 的 m 个室友会吃他的,编号
1 到 m. 第  j 个室友会在 lj到 rj
天和他一起住且每天吃 fj kg食物.
Vasya 每天可以给同住的人  j  fj kg食物(可以选一些人分).Vasya每一次分食物都要让人吃饱(要不然不厚道).

Vasya 怎样分出最多次食物?

Input

第一行2个整数 n 和 v (1 ≤ n, v ≤ 400).
第2行 n 个整数 a1, a2, ..., an (1 ≤ ai ≤ 400), 

第三行一个整数 m (1 ≤ m ≤ 400). 接下来 m 行每行3个整数.第
 j 行为 lj, rj, fj (1 ≤ lj ≤ rj ≤ n, 1 ≤ fj ≤ 400).

Output

第一行输出最多分出食物次数. 接下来 n 行第一行输出第 天分几次.接下来输出当天分的朋友的编号(任意顺序).若有多解任意输出一种.

Sample test(s)
input
4 1
3 2 5 4
3
1 3 2
1 4 1
3 4 2
output
7
1 2
1 2
3 2 1 3
2 2 3

Dp题,主要推方程。

显然每天从食量最小的贪起。

为了处理食物隔夜问题,多留一维表示昨天剩下的食物。

由于不好求出向前的方程,也不知道终态,所以要从当前向后递推(而非从前面向当前递推,类似矿工食堂的解决方案)


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iostream>
#include<vector>
using namespace std;
#define MAXN (400+10)
#define MAXV (400+10)
#define MAXAi (400+10)
#define MAXM (400+10)
#define TomorrowFood (min(a[i],x))
#define _Next_ [i+1][TomorrowFood]
int n,m,v;
vector <pair< int,int> > man[MAXN]; // ith day jth man eat k food. //pair(j,k)
int a[MAXN]={0};
int f[MAXN][MAXV*2]={0}; // ith day havv j food left last night,->rat
int totlastf[MAXN][MAXV*2]={0}; //昨晚几个人吃
int last[MAXN][MAXV*2]={0};   //昨晚剩多少
int solve(int i,int j)
{
	if (i>2) solve(i-1,last[i][j]); //{ n+1->n n->n-1 ... 2->1 }   1->0
	cout<<totlastf[i][j];
	for (int k=1;k<=totlastf[i][j];k++)
		cout<<' '<<man[i-1][k].second;
	cout<<endl;
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	cin>>n>>v;
	for (int i=1;i<=n;i++){cin>>a[i]; man[i].push_back(make_pair(0,0)); }
	cin>>m;
	for (int i=1;i<=m;i++)
	{
		int l,r,fi; cin>>l>>r>>fi; //fi=food in a man
		for (int j=l;j<=r;j++)
			man[j].push_back(make_pair(fi,i));
	}
	for (int i=1;i<=n;i++) sort(man[i].begin(),man[i].end());

	memset(f,128,sizeof(f));
	f[1][0]=0;

	for (int i=1;i<=n;i++)
	{
		for (int j=0;j<=a[i-1];j++) //昨晚最多留下a[i] food(其它过期)
		{
			int x=j-v+a[i];  //表示昨天剩下的,吃了v,又多了今天的a[i]
			if (x<0) continue; //一定够吃
			if (f[i+1][TomorrowFood]<f[i][j])
			{
				f[i+1][TomorrowFood]=f[i][j];
				totlastf[i+1][TomorrowFood]=0;
				last _Next_ =j;
			}
			for (int k=1;k<man[i].size();k++)
			{
				x-=man[i][k].first;
				if (x<0) break;
				if (f[i+1][TomorrowFood]<f[i][j]+k)
				{
					f[i+1][TomorrowFood]=f[i][j]+k;
					totlastf[i+1][TomorrowFood]=k;
					last _Next_ =j;
				}
			}
		}
	}

	int ans=-1,now;
	for (int j=0;j<=MAXV;j++)
		if (ans<f[n+1][j]) {ans=f[n+1][j]; now=j; }
	cout<<ans<<endl;
	solve(n+1,now);
	return 0;
}

CF 253D(矩阵-4角相等且矩阵权值有上限的矩阵数)

D. 4a矩阵
time limit per test

2 seconds

memory limit per test

256 megabytes

input

input.txt

output

output.txt

有一个 n × m 的矩阵, 行 1 到 n,
列1 to 
m.

4a矩阵定义:

  • 矩阵内最多有 k 个 "a" ;
  • 4个角相等,长宽大于1.

请在给定矩阵中数出有几个子矩阵是4a矩阵.

Input

第一行3个整数n, m, k (2 ≤ n, m ≤ 400; 0 ≤ k ≤ n·m).

接下来为矩阵.

Output

一个整数,表示4a矩阵数.

Sample test(s)
input
3 4 4
aabb
baab
baab
output
2
input
4 5 1
ababa
ccaca
ccacb
cbabc
output
1
Note

第一个样例的解 (2, 2) (3, 3),

(2, 1) 
(3, 4).

这题是状态压缩问题。

用s[i][j]=∑a[1][j]+a[2][j]+..+a[i][j]

那么我们只需要枚举3个量

行的上下,还有列的

显然r列的关系可以由r-1的关系推出。



#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cstdlib>
using namespace std;
#define MAXN (400+10)
#define MAXM (400+10)
int n,m,k;
char a[MAXN][MAXM];
int s[MAXN][MAXM];  //表示s[i][j]=a[1][j]+a[2][j]+..a[i][j]
int c[1<<8];
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);


	memset(s,0,sizeof(s));
	scanf("%d%d%dn",&n,&m,&k);
	for (int i=1;i<=n;i++)
	{
		gets(a[i]+1);
		for (int j=1;j<=m;j++)
		{
			s[i][j]=s[i-1][j]+(a[i][j]=='a');
		}
	}
	long long ans=0;
	/*
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
			cout<<s[i][j]<<' ';
		cout<<endl;
	}
	*/
	;
	for (int i=1;i<n;i++)
	{
		for (int j=i+1;j<=n;j++)
		{
			int l=1,tot=0;
			memset(c,0,sizeof(c));
			for (int r=1;r<=m;r++)
			{
				tot+=s[j][r]-s[i-1][r];
				while (tot>k)
				{
					tot-=s[j][l]-s[i-1][l];
					c[a[i][l]]-=(a[i][l]==a[j][l]);
					l++;
				}
				if (l<r&&a[i][r]==a[j][r]) ans+=c[a[i][r]];
				if (a[i][r]==a[j][r]) c[a[i][r]]++;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

CF 254C(易位构字法)

C. 易位构字法
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

异位构字就是把一个字符串的顺序改变,可以得到另一个字符串.

对字符串 s 和 t ,至少修改 s 多少位,能使 s 和 t 易位构字?如果有很多方法,输出 s 易位后字典序最小的。

Input

两行 st. 长度不超过 105 ,只有大写字母。

Output

第一行输出最小修改次数,第二行输出 s 修改后字典序最小的字符串。

Sample test(s)
input
ABA
CBA
output
1
ABC
input
CDBABC
ADCABD
output
2
ADBADC
Note

 第二个数据,s 可改成: "ADBADC", "ADDABC",
"CDAABD", "CDBAAD", "CDBADA",
"CDDABA", "DDAABC", "DDBAAC".
字典序最小的是 "ADBADC".

直接处理字符串。

program word;
const
   maxn=100000;
var
   s,t:ansistring;//->ansistring
   n,i,j,ans,size,head:longint;
   pass,a1,a2,deln:array['A'..'Z'] of longint;
   add:array[1..26] of char;
   addn:array[1..26] of longint;
   ic:char;
begin
   assign(input,'input.txt');
   assign(output,'output.txt');
   reset(input);
   rewrite(output);
   fillchar(a1,sizeof(a1),0);
   fillchar(a2,sizeof(a2),0);
   fillchar(pass,sizeof(pass),0);
   fillchar(deln,sizeof(deln),0);
   readln(s);
   readln(t);
   n:=length(s);
   for i:=1 to n do inc(a1[s[i]]);
   for i:=1 to n do inc(a2[t[i]]);

   size:=0;
   ans:=0;
   for ic:='A' to 'Z' do
      if a2[ic]>a1[ic] then
      begin
         inc(size);
         add[size]:=ic;
         addn[size]:=a2[ic]-a1[ic];
         inc(ans,addn[size]);
      end
      else if a2[ic]<a1[ic] then
      begin
         deln[ic]:=a1[ic]-a2[ic];
      end;

   writeln(ans);
   head:=1;
   for i:=1 to n do
   begin
      inc(pass[s[i]]);
      if deln[s[i]]>0 then
      begin
         if (add[head]<s[i]) or (deln[s[i]]>a1[s[i]]-pass[s[i]]) then
         begin
            dec(deln[s[i]]);
            s[i]:=add[head];
            dec(addn[head]);
            if addn[head]=0 then inc(head);
         end;
      end;
   end;
   writeln(s);
   close(input);
   close(output);
end.

CF 254B(日期)

B. 评委会
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

2013年要举办 n 场比赛,编号1 到 n. 每场比赛需要人准备(在开幕的前 ti 天(不包括开幕当天))

如果准备时间重复,一个人一天只能为一场比赛准备,请问最少需要雇多少人准备?

Input

第一行一个整数 n  (1 ≤ n ≤ 100). 接下来 n 行每行为midipi 和 ti —
开幕的月份,日期,每天需要的人数,准备天数 (1 ≤ mi ≤ 12di ≥ 11 ≤ pi, ti ≤ 100),输入顺序任意,一天可能有同时多场比赛开幕。

非润年,二月28天. 可能需要在2012年某天开始准备.

Output

输出最小人数。

Sample test(s)
input
2
5 23 1 2
3 13 2 3
output
2
input
3
12 9 2 1
12 8 1 3
12 8 2 2
output
3
input
1
1 10 1 13
output
1

直接模拟,注意日期换算。


Program jury;
var
   n,i,j,m,d,p,t,ans:longint;
   month:array[1..12] of longint=(31,28,31,30,31,30,31,31,30,31,30,31);
   a:array[-1000..1000] of longint;
begin
   assign(input,'input.txt');
   assign(output,'output.txt');
   reset(input);
   rewrite(output);
   read(n);
   fillchar(a,sizeof(a),0);
   for i:=1 to n do
   begin
      read(m,d,p,t);
      for j:=1 to m-1 do inc(d,month[j]);
      for j:=d-1 downto d-t do
         inc(a[j],p);
   end;
   ans:=0;
   for i:=-1000 to 1000 do
      if ans<a[i] then ans:=a[i];
   writeln(ans);

   close(input);
   close(output);
end.

CF 254A(重复的数)

A. 数字卡片
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

2n张卡片编号为1 .. 2n.卡片数字相同可凑成一对,能否凑完?

Input

第一行1个整数n (1 ≤ n ≤ 3·105).
第二行有2n个整数a1, a2, ..., a2n (1 ≤ ai ≤ 5000)
表示第i张卡片的数字。

Output

如果凑不完,请输出 -1.否则输出 n 行,每行一对对整数,表示第i张卡片与第j张凑成一对。

输出任意方案。

Sample test(s)
input
3
20 30 10 30 20 10
output
4 2
1 5
6 3
input
1
1 2
output
-1

直接用数组记录出现次数,每遇到一对,就扔入解中。

Program Cards;
const
   maxn=300000;
var
   n,i,p,size:longint;
   a:array[1..5000] of longint;
   q1,q2:array[1..maxn] of longint;
begin
   assign(input,'input.txt');
   assign(output,'output.txt');
   reset(input);
   rewrite(output);

   read(n);
   fillchar(a,sizeof(a),0);
   size:=1;
   for i:=1 to 2*n do
   begin
      read(p);
      if a[p]>0 then
      begin
         q1[size]:=a[p];q2[size]:=i;
         inc(size);
         a[p]:=0;
      end
      else a[p]:=i;
   end;
   if size<>n+1 then writeln('-1')
   else for i:=1 to n do writeln(q1[i],' ',q2[i]);

   close(input);
   close(output);
end.

CF 253C(找中转行)

C. 光标移动
time limit per test

1 second

memory limit per test

256 megabytes

input

input.txt

output

output.txt

文本编辑器有n行,每行k个字符(显然光标有k+1个位置,标记为1..k+1.

有4个操作:

  • "Up": 光标将向上移1行,列不变。如果上一行字符太少,则光标跑到行末。

  • "Down":
    光标将向下移1行,列不变。如果上一行字符太少,则光标跑到行末。

  • "Right": 光标向右移1格,操作不能在行末进行。

  • "Left":
    光标向左移1格,操作不能在行首进行。

    求出把光标从 (r1, c1) 移向(r2, c2)最小步数.

  • Input

    第一行一个整数 n (1 ≤ n ≤ 100) . 第二行 n个整数a1, a2, ..., an (0 ≤ ai ≤ 105),
    表示每行字符数. 第三行4个整数 r1, c1, r2, c2 (1 ≤ r1, r2 ≤ n, 1 ≤ c1 ≤ ar1 + 1, 1 ≤ c2 ≤ ar2 + 1).

    Output

    输出最小步数

    Sample test(s)
    input
    4
    2 1 6 4
    3 4 4 2
    
    output
    3
    
    input
    4
    10 5 6 4
    1 11 4 2
    
    output
    6
    
    input
    3
    10 1 10
    1 10 1 1
    
    output
    3
    
    Note

    第一组数据若为

    123

    12

    123s567

    1t345

    则最小操作为 "Left", "Down", "Left".

    显然除了直接移(先行后列)外,

    唯一减少操作数的方法便是向中间以外的行数移,以求降低列的移动数。

    一定要注意不是挪到每行直接取abs(行尾-c2)的,因为可能会有往返行尾的路上有更小的,直接取行尾可能拉近它和c2的距离,但是这种操作是不可行的。

    #include<cstdio>
    #include<functional>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define MAXN (10000+100)
    int a[MAXN],n;
    int abs2(int a,int b)
    {
    	if (a<b) return b-a;
    	else return a-b;
    }
    int main()
    {
    	freopen("input.txt","r",stdin);
    	freopen("output.txt","w",stdout);
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	int r1,c1,r2,c2;
    	scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
    	int mi=c1,ans=0,tans=1000000000;
    	if (r1<r2)
    	{
    		ans=r2-r1;
    		for (int i=r1+1;i<=r2;i++) mi=min(mi,a[i]+1);
    		tans=min(tans,ans+abs(mi-c2));
    		for (int i=r1-1,cost=2,mii=mi;i>=1;i--,cost+=2)
    		{
    			mii=min(mii,a[i]+1);
    			tans=min(tans,ans+cost+abs(mii-c2));
    		}
    		for (int i=r2+1,cost=2,mii=mi;i<=n;i++,cost+=2)
    		{
    			mii=min(mii,a[i]+1);
    			tans=min(tans,ans+cost+abs(mii-c2));
    		}
    	}
    	else
    	{
    		ans=r1-r2;
    		for (int i=r1-1;i>=r2;i--) mi=min(mi,a[i]+1);
    		tans=min(tans,ans+abs(mi-c2));
    		for (int i=r2-1,cost=2,mii=mi;i>=1;i--,cost+=2)
    		{
    			mii=min(mii,a[i]+1);
    			tans=min(tans,ans+cost+abs(mii-c2));
    		}
    		for (int i=r1+1,cost=2,mii=mi;i<=n;i++,cost+=2)
    		{
    			mii=min(mii,a[i]+1);
    			tans=min(tans,ans+cost+abs(mii-c2));
    		}
    	}
    	cout<<tans<<endl;
    	return 0;
    }

    CF 253B(队列上维护2个指针后移)

    B. 实验误差
    time limit per test

    1 second

    memory limit per test

    256 megabytes

    input

    input.txt

    output

    output.txt

    小明做实验,测了n次结果,因为误差,这些结果不一样。

    至少修改多少结果,才能使最大的结果不超过最小的结果的2倍?

    Input

    第一行一个整数 n (2 ≤ n ≤ 105),第二行有n个数c1, c2, ..., cn表示结果(1 ≤ ci ≤ 5000)

    Output

    输出一个整数,表示最小修改次数。

    Sample test(s)
    input
    6
    4 5 3 8 3 7
    
    output
    2
    
    input
    4
    4 3 2 4
    
    output
    0
    
    Note

    第1个数据删除8,7,第二个数据本身就满足条件。

    排序,从小到大枚举最小数,并把后指针挪向最大的不用修改的数进行统计即可。


    #include<cstdio>
    #include<functional>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define MAXN (100000+100)
    int a[MAXN];
    int n;
    int main()
    {
    	freopen("input.txt","r",stdin);
    	freopen("output.txt","w",stdout);
    
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	a[n+1]=1000000;
    //	for (int i=1;i<=n;i++) cout<<a[i]<<' ';cout<<endl;
    	int t=1,ans=0;
    	for (int h=1;h<=n;h++)
    	{
    		while (a[h]*2>=a[t+1]) t++;
    		ans=max(ans,t-h+1);
    	}
    	cout<<n-ans<<endl;
    
    }
    



    CF 253A(最大间隔相异队列)

    A. 男孩女孩
    time limit per test

    1 second

    memory limit per test

    256 megabytes

    input

    input.txt

    output

    output.txt

    有n个男孩和m个女孩排队,我们希望相邻的2个孩子性别尽可能不同。

    请帮助它们排队。

    Input

    第1行有2个整数 n,m (1 ≤ n, m ≤ 100).

    Output

    请输出一行它们排队的队列,B表示男孩,G表示女孩.

    输出任意一种方案即可。

    Sample test(s)
    input
    3 3
    
    output
    GBGBGB
    
    input
    4 2
    
    output
    BGBGBB
    
    Note

    In the first sample another possible answer is BGBGBG.

    In the second sample answer BBGBGB is also optimal.

    分成2种情况考虑-男多女少和女多男少

    考虑以下2种情况:

    BGBGBB

    BGBGGG-->GBGBGG 显然后面间隔较多


    Program Boys;
    var
       n,m,i:longint;
    begin
       assign(input,'input.txt');
       assign(output,'output.txt');
       reset(input);
       rewrite(output);
       read(n,m);
       if n<m then
       begin
          for i:=1 to n do write('GB');
          for i:=n+1 to m do write('G');
       end
       else
       begin
          for i:=1 to m do write('BG');
          for i:=m+1 to n do write('B');
       end;
       writeln;
    
       close(input);close(output);
    end.

    ZOJ 1576(稳定婚姻系统-重名)

    Marriage is Stable

    Time Limit: 5 Seconds
    Memory Limit:
    32768 KB Special Judge


    Albert, Brad, Chuck are happy bachelors who are in love with Laura, Marcy, Nancy. They all have three choices. But in fact, they do have some preference in mind. Say Albert, he likes Laura best, but that doesn't necesarily mean Laura likes him. Laura likes
    Chuck more than Albert. So if Albert can't marry Laura, he thinks Nancy a sensible choice. For Albert, he orders the girls Laura > Nancy > Marcy.

    For the boys:

    Albert: Laura > Nancy > Marcy
    Brad: Marcy > Nancy > Laura
    Chuck: Laura > Marcy > Nancy

    For the girls:

    Laura: Chuck > Albert > Brad
    Marcy: Albert > Chuck > Brad
    Nancy: Brad > Albert > Chuck

    But if they were matched randomly, such as

    Albert <-> Laura
    Brad <-> Marcy
    Chuck <-> Nancy

    they would soon discover it's not a nice solution. For Laura, she likes Chuck instead of Albert. And what's more, Chuck likes Laura better than Nancy. So Laura and Chuck are likely to come together, leaving poor Albert and Nancy.

    Now it's your turn to find a stable marriage. A stable marriage means for any boy G and girl M, with their choice m[G] and m[M], it will not happen that rank(G, M) < rank(G, m[G]��and rank(M, G) < rank(M, m[M]).

    Input

    Each case starts with an integer n (1 <= n <= 500), the number of matches to make.

    The following n lines contain n + 1 names each, the first being name of the boy, and rest being the rank of the girls.

    The following n lines are the same information for the girls.

    Process to the end of file.

    Output

    If there is a stable marriage, print n lines with two names on each line. You can choose any one if there are multiple solution. Print "Impossible" otherwise.

    Print a blank line after each test.

    Sample Input

    3
    Albert Laura Nancy Marcy
    Brad Marcy Nancy Laura
    Chuck Laura Marcy Nancy
    Laura Chuck Albert Brad
    Marcy Albert Chuck Brad
    Nancy Brad Albert Chuck

    Sample Output

    Albert Nancy
    Brad Marcy
    Chuck Laura

    这题就是稳定婚姻系统,

    注意有同名的男女。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<functional>
    #include<algorithm>
    #include<queue>
    #include<iostream>
    #include<map>
    #include<string>
    using namespace std;
    #define MAXN (2000+10)
    int n;
    queue<int> q;
    map<string,int> hpos_male,hpos_female;
    
    int female_like[MAXN][MAXN];  //SIS
    int male_like[MAXN][MAXN];    //SSI
    int match[MAXN];
    string a[MAXN];
    int main()
    {
    //	freopen("zoj1576.in","r",stdin);
    	while (scanf("%d",&n)!=EOF)
    	{
    		hpos_male.clear();
    		hpos_female.clear();
    		memset(match,0,sizeof(match));
    		int size=n+1;
    		for (int i=1;i<=n;i++)
    		{
    			cin>>a[i];hpos_male[a[i]]=i; q.push(i);
    			for (int j=1;j<=n;j++)
    			{
    				string s;
    				cin>>s;
    				if (i==1)
    				{
    					hpos_female[s]=size;
    					a[size]=s;
    					size++;
    				}
    				male_like[i][j]=hpos_female[s];
    			}
    		}
    		for (int i=n+1;i<=2*n;i++)
    		{
    			string sg;
    			cin>>sg;
    			for (int j=1;j<=n;j++)
    			{
    				string s;
    				cin>>s;
    				female_like[hpos_female[sg]][hpos_male[s]]=j;
    			}
    		}
    		/*
    		for (int i=n+1;i<=2*n;i++)
    		{
    			for (int j=1;j<=n;j++)
    				cout<<female_like[make_pair(a[i],a[j])]<<' ';
    			cout<<endl;
    		}
    		*/
    		while (!q.empty())
    		{
    			int now=q.front();
    			q.pop();
    			for (int j=1;j<=n;j++)
    			{
    				int v=male_like[now][j];
    				if (!match[v])
    				{
    					match[now]=v;match[v]=now;//cout<<now<<' '<<v<<endl;
    					break;
    				}
    				else if (female_like[v][match[v]]>female_like[v][now])
    				{
    					q.push(match[v]);
    					match[match[v]]=0;
    					match[now]=v;match[v]=now;//cout<<now<<' '<<v<<endl;
    					break;
    				}
    			}
    		}
    		for (int i=1;i<=n;i++)
    		{
    			cout<<a[i]<<' '<<a[match[i]]<<endl;
    		}
    		printf("n");
    	}
    	return 0;
    }