USACO / Controlling Companies (类似BFS)

题目    

有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分。例如,福特公司拥有马自达公司12%的股票。据说,如果至少满足了以下三个条件之一,公司A就可以控制公司B了:

  1. 公司A = 公司B。
  2. 公司A拥有大于50%的公司B的股票。
  3. 公司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%的股份。

样例输入 (file concom.in)

3

1 2 80

2 3 80

3 1 20

输出格式

输出零个或更多个的控制其他公司的公司。每行包括两个整数A、B,表示A公司控制了B公司。将输出的数对以升序排列。

请不要输出控制自己的公司(应该是不输出自己,互相控制的公司还是要输出的)。

样例输出 (file concom.out)

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;

}

 

 

你可能感兴趣的:(USACO)