USACO Section2.3 Controlling Companies 解题报告 【icedream61】
concom解题报告
------------------------------------------------------------------------------------------------------------------------------------------------
【题目】
有至多100个公司,每个公司可能会有很多子公司,请你输出每个公司有哪些子公司。
B是A的子公司,有以下两种情况:
1. A拥有B超过50%的股份
2. A某些子公司(包括A自己)各拥有的B的股份加起来,超过50%
【输入格式】
第一行n,表示有n个股份关系。
有n行,每行给出三个数u,v,c,表示u公司拥有v公司c%的股份。
【输出格式】
每一行(u,v)表示v是u的子公司。
输出所有的(u,v),保证u升序,然后再保证v升序。
【输入样例】
3
1 2 80
2 3 80
3 1 20
【输出样例】
1 2
1 3
2 3
------------------------------------------------------------------------------------------------------------------------------------------------
【分析】
建个图,在里面用SPFA(Bellman-Ford)的思路来求解。不了解SPFA的同学,可以去看我之前的文章:“《算法》C++代码 SPFA”。
把所有公司建成一个图,u拥有v股份c,就连一条边(u,v)=c。
我们依次判断每个公司拥有哪些子公司。
假设我们现在在考虑S公司,那么步骤如下:
1. 开始只有S公司自己,设为集合A。
2. 进入死循环1号,令p=false
3. 枚举所有集合A外的公司v,对每个v:
2.1 设s=0
2.2 枚举所有集合A内的公司u,若存在边(u,v)=c,则s+=c。
2.3 若s>50,说明v是S的子公司,并把v加入集合A,令p=true
3. 若p==true,则说明此轮发现了新的子公司,什么也不做,回归死循环1号;若p==false,则说明此轮并未发现子公司,那么退出死循环1号
4. 至此,集合A便是S的所有子公司(包括S自己),按照升序输出即可
而外围,只要保证所考虑的S公司也是升序,就可以保证最终结果完全升序了。
分析时间,100个公司,而每个公司死循环1号执行一轮的时间是100,每轮至少找到一个子公司,因此死循环1号至多执行100轮。
总计时间:100*100*100=1000000,没问题。
------------------------------------------------------------------------------------------------------------------------------------------------
【总结】
第二次AC。
第一次没保证每个公司的子公司是升序输出的-.-
------------------------------------------------------------------------------------------------------------------------------------------------
【代码】
1 /* 2 ID: icedrea1 3 PROB: concom 4 LANG: C++ 5 */ 6 7 #include <iostream> 8 #include <fstream> 9 using namespace std; 10 11 const int N=100; 12 bool have[1+N]; 13 14 int E[1+N][1+N]; 15 16 void look(int S,ostream& out) 17 { 18 int A[N],Ai=0,Aj=0; 19 bool IN[1+N]={},R[1+N]={}; 20 A[Aj++]=S; IN[S]=true; 21 while(true) 22 { 23 bool p=false; 24 for(int v=1;v<=N;++v) 25 if(have[v] && !IN[v]) 26 { 27 int s=0; 28 for(int i=Ai;i!=Aj;++i) 29 { 30 int u=A[i]; s+=E[u][v]; 31 } 32 if(s>50) 33 { 34 R[v]=true; 35 A[Aj++]=v; IN[v]=true; 36 p=true; 37 } 38 } 39 if(p==false) break; 40 } 41 for(int i=1;i<=N;++i) 42 if(R[i]) out<<S<<' '<<i<<endl; 43 } 44 45 int main() 46 { 47 ifstream in("concom.in"); 48 ofstream out("concom.out"); 49 50 int M; in>>M; 51 for(int i=1,u,v,c;i<=M;++i) { in>>u>>v>>c; have[u]=have[v]=true; E[u][v]=c; } 52 53 for(int i=1;i<=N;++i) 54 if(have[i]) look(i,out); 55 56 in.close(); 57 out.close(); 58 return 0; 59 }
posted on 2015-05-23 19:52 IceDream61 阅读(379) 评论(0) 编辑 收藏 举报