1. 程式人生 > >【題解:洛谷 1475||USACO 2.3 控制公司Controlling Companies】

【題解:洛谷 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;
}