题目大意


有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分。例如,福特公司拥有马自达公司12%的股票。据说,如果至少满足了以下三个条件之一,公司A就可以控制公司B了:

  • 公司A = 公司B。
  • 公司A拥有大于50%的公司B的股票。
  • 公司A控制K(K >= 1)个公司,记为C1, …, CK,每个公司Ci拥有xi%的公司B的股票,并且x1+ …. + xK > 50%。

给你一个表,每行包括三个数(i,j,p);表明公司i享有公司j的p%的股票。计算所有的数对(h,s),表明公司h控制公司s。至多有100个公司。写一个程序读入N组数(i,j,p),i,j和p是都在范围(1..100)的正整数,并且找出所有的数对(h,s),使得公司h控制公司s。

思路


搜索。若公司a可以控制公司b,就将b的控股信息更新到a上,若发现有新的公司c可以被a所控制,则再把c的信息更新到a上,这由一个递归过程来体现。搜索完成后将结果排序输出即可。

代码


/*
ID: lujunda1
LANG: C++
PROG: concom
*/
#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;

#define size 100

int map[size+1][size+1],n;
//map[i][j]==x表示i公司持有j的x%的股份。
int res[size*size][2],total;
//res[][]存储结果,total是结果的数量。 

void init()
//初始化 
{
	memset(map,0,sizeof(map));
	total=0;
}

void update(int x,int y,int now)
//x公司控制y公司,将y公司持股信息更新到x公司上。
//now表示func函数的进度,用于避免重复计算。 
{
	res[total][0]=x;
	res[total++][1]=y;
	//x控制y公司,先更新res数组。 
	for(int i=1;i<=size;i++)
		if(i!=x&&map[x][i]<=50)
		//只需要更新那些尚未被x控制的公司的信息即可。所以map[x][i]<=50。 
		{
			map[x][i]+=map[y][i];
			if(map[x][i]>50&&i<now)
			//如果i<now,func()函数不会再次调用update(x,i,i),需要在这里递归更新。
			//如果i>now,func()会在后面调用update(x,i,i),不需要现在更新。 
				update(x,i,now);
		}
}

void func(int x)
//检查x公司的控股情况 
{
	for(int i=1;i<=size;i++)
		if(i!=x&&map[x][i]>50)
			update(x,i,i);
}

int cmp(const void* m,const void* n)
//对二维数组res排序 
{
	if(*(int*)m==*(int*)n)
		return *((int*)m+1)-*((int*)n+1);
	return *(int*)m-*(int*)n;
}

int main()
{
	freopen("concom.in","r",stdin);
	freopen("concom.out","w",stdout);
	init();
	scanf("%d",&n);
	for(int i,j,k;n--;)
	{
		scanf("%d%d%d",&i,&j,&k);
		map[i][j]=k;
	}
	for(int i=1;i<=size;i++)
		func(i);
	qsort(res,total,sizeof(res[0]),cmp);
	//对结果进行排序。 
	for(int i=0;i<total;i++)
		printf("%d %d\n",res[i][0],res[i][1]);
}