题目大意
有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分。例如,福特公司拥有马自达公司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]); }