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  阅读(370)  评论(0编辑  收藏  举报

导航