Controlling Companies
控制公司
给你一个表,每行包括三个数(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%的股份。
3 1 2 80 2 3 80 3 1 20
输出零个或更多个的控制其他公司的公司。每行包括两个整数A、B,表示A公司控制了B公司。将输出的数对以升序排列。
请不要输出控制自己的公司(应该是不输出自己,互相控制的公司还是要输出的)。
1 2 1 3 2 3
分析:
这道题刚开始自己看着还挺麻烦,不想写。不过仔细研究一下就发现是个很简单的搜索题。
设f[i][j]是i公司直接控j公司多少股,p[i][j]是i公司直接+间接控j公司多少股,h[i][j]表示i公司是否可以控制j公司。
首先把所有直接可以控制的关系添加进去,然后开始枚举更新所有公司的间接持股,没枚举完一次就判断是否添加了新控制关系,而每添加一组控制关系就要再把所有的关系更新一遍(看到这里我就突然想到了Dijkstra,每确定一个点都要松弛一次,然后恍然大悟,学算法不仅要理解表面,还要学习它里面包含的思想~~~)
代码:
/* ID: 138_3531 PROB: concom LANG: C++ */ #include<iostream> #include<fstream> #include<cstring> using namespace std; int f[101][101],p[101][101]; char h[101][101]; int n; ifstream fin("concom.in"); ofstream fout("concom.out"); int main() { int max=0; fin>>n; memset(h,0,sizeof(h)); memset(f,0,sizeof(f)); for (int i=0;i<n;i++) { int x,y; fin>>x>>y; if (x>max) max=x; if (y>max) max=y; fin>>f[x][y]; if (f[x][y]>50) h[x][y]=1; } int ok=1; while (ok) { ok=0; memset(p,0,sizeof(p)); for (int i=1;i<=max;i++) for (int j=1;j<=max;j++) p[i][j]=f[i][j]; for (int i=1;i<=max;i++) for (int j=1;j<=max;j++) if (h[i][j]) for (int k=1;k<=max;k++) p[i][k]+=f[j][k]; for (int i=1;i<=max;i++) for (int j=1;j<=max;j++) if ((p[i][j]>50)&&(h[i][j]==0)) { h[i][j]=1; ok=1; } } for (int i=1;i<=max;i++) for (int j=1;j<=max;j++) if ((h[i][j])&&(i!=j)) fout<<i<<' '<<j<<endl; return 0; }