【题解:洛谷 1475||USACO 2.3 控制公司Controlling Companies】

[传送门]:(https://www.luogu.org/problemnew/show/P1475)
题目描述
有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分。(此处略去一句废话)据说,如果至少满足了以下三个条件之一,公司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。

输入输出格式
输入格式:
第一行: N,表明接下来三个数的数量,即(i,j,p)的数量。

第二行到第N+1行: 每行三个整数作为一个三对数(i,j,p),表示i公司拥有j公司 p%的股份。

输出格式:
输出零个或更多个的控制其他公司的公司。每行包括两个整数A、B,表示A公司控制了B公司。将输出的数对以升序排列。

请不要输出控制自己的公司(应该是不输出自己,互相控制的公司还是要输出的)。

输入输出样例
输入样例#1:
3
1 2 80
2 3 80
3 1 20
输出样例#1:
1 2
1 3
2 3
Analysis
一开始觉得是图论,后来觉得dfs貌似更靠谱~~不过话说图论好像也可以耶。。。
attention:
公司A只能拥有它的子公司(我们把直系的所属公司称为子公司)的股份,也就是说如果A有40%的B公司,B有60%的C公司,那么此时A公司与C公司半毛钱关系也没有。
所以我们注意到,A公司拥有哪些公司,只取决于A自己的股份情况和A的已知所属公司的股分情况,故dfs时只需考虑这两点就OK了。
对于当前节点i,先跑一遍所有点,同时判断该点是否为当前节点i的子公司,如果是就dfs该节点,否则跳过。
explain:
cpy[i]:公司i是否被当前分析的公司控制;
val[i]:当前分析的公司及其每一个所属公司(不只是子公司)总共有公司i的股份(有点绕)。
由于cpy和val都只针对当前分析的公司,所以注意清零!!!!

贴上代码:

#include<bits/stdc++.h> 
using namespace std;
int mp[101][101];
inline int read(){
	char ch;
	while((ch=getchar())<'0'||ch>'9') ;
	int ans=ch-48;
	while((ch=getchar())>='0'&&ch<='9')
		ans=ans*10+ch-48;
	return ans;	
}
inline void write(int x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
	return;
}
int cpy[101],val[101];
int n;
inline void dfs(int x){
	for(int i=1;i<=100;i++){
		val[i]+=mp[x][i];
		if(val[i]>50&&!cpy[i]) cpy[i]=1,dfs(i);
	}
}
int main(){
	memset(mp,0,sizeof(mp));
	n=read();
	int x,y,p;
	for(int i=1;i<=n;i++)
		x=read(),y=read(),mp[x][y]=read();
	for(int i=1;i<=100;i++){
		memset(cpy,0,sizeof(cpy));
		memset(val,0,sizeof(val));
		dfs(i);
		for(int j=1;j<=100;j++)
			if(cpy[j]&&i!=j) write(i),putchar(' '),write(j),putchar('\n');
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43263852/article/details/86327449
2.3