控股公司(usaco training 2.3)
前言:本题强烈建议手画公司之间的关系图来辅助理解。😃
一些公司会通过购买其他公司的部分股份以达到控制这些公司的目的。
一般来说,如果能够满足以下条件中的至少一项,则公司 A 将会控制公司 B:
公司 A = 公司 B
公司 A 持有公司 B 超过 50% 的股份
公司 A 控制着 K 个公司,这些公司表示为 C1,C2,…,CK,公司 Ci 持有的公司 B 的股份为 Xi%,X1+…+XK>50
注意:
控股关系具有传递性,即如果公司 A 控股公司 B,公司 B 控股公司 C,那么公司 A 控股公司 C。
数据保证控股关系不存在环。
给定一个三元组列表,列表中的每个三元组 (i,j,p) 表示公司 i 持有公司 j 的 p% 的股份。
我们用数对 (h,s) 来表示公司 h 控制着公司 s。
现在,请你找到并输出所有成立的数对 (h,s)。
输入格式
第一行包含整数 N,表示三元组列表中三元组的数量。
接下来 N 行,每行包含三个整数 i,j,p,意义如上所述。
输出格式
每行包含两个整数 h,s,表示公司 h 控制着公司 s。
输出所有满足条件的数对。
输出时,按第一个数升序排序输出,第一个数相同时,按第二个数升序排序输出。
另外,一个公司控制着自己,这种关系不需要输出。
数据范围
公司总数量不会超过 100,
1≤i,j,p≤100,
1≤N≤2600
输入样例:
3
1 2 80
2 3 80
3 1 20
输出样例:
1 2
1 3
2 3
思路:
没错,这又双叒叕是一道usaco的题,但是,它居然没有奶牛?没有奶牛的usaco题是没有灵魂的。
废话不多说,马上来看题,这道题第一眼看上去不知所措,再看,好似并查集!但是,我太蒻了,只能在数据规模不大的题里用电风扇 DFS苟一波。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<climits>
using namespace std;
int a[120][120];//a[i][j] = 公司i对公司j所持有的股份
int b[120][120];//b[i][j] = 公司i控制公司j
int n = 100;
int m;
void dfs(int,int);
int main()
{
cin >> m;
for(int i = 1;i <= n;++i)
{
b[i][i] = true; //公司可以自己控制自己
}
while(m--)
{
int x,y,z;
cin >> x >> y >> z;
for(int i = 1;i <= n;++i)
{
if(b[i][x]) //如果x公司被i公司控制
{
a[i][y] += z;//那么x公司对y公司的股份,也要加入i公司对y公司所间接持有的股份(传递性)
}
if(a[i][y] > 50) dfs(i,y);//如果i公司对y公司的股份持有大于50%,调用dfs更新关系
}
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
if(i != j&&b[i][j])
{
cout << i << " " << j << endl;
}
}
}
return 0;
}
void dfs(int x,int y)
{
if(b[x][y]) return ;//如果x公司已经控股y公司,直接结束,不用重复更新
b[x][y] = true;
for(int i = 1;i <= n;++i)
{
a[x][i] += a[y][i];//x已控股y,y对i的股份加入x对i的股份
}
for(int i = 1;i <= n;++i)
{
if(b[i][x])
{
dfs(i,y); //因为x控股y,而i又控股x,所以i控股y
}
}
for(int i = 1;i <= n;++i)
{
if(a[x][i] > 50)
{
dfs(x,i); //x控股i,更新
}
}
}
感谢你的阅读,希望这篇博客能帮到你!