竞赛于 2016-4-19 T1,公司控制(usaco 原题)

来源:互联网 发布:手机控制wifi软件 编辑:程序博客网 时间:2024/05/20 12:50

该题为USACO上原题,乍一看挺麻烦,其实可直接搜索。设a[i][j]为i公司控制j公司的股份,con[i][j]表示i公司是否控制j公司。首先枚举每个i,j公司,对于每个i能控制的公司j,则要继续枚举j占有股份的公司k,计算其股份和,跟新a[i][k],然后添加i控制j,而每次添加新的控制关系则要再更新一次所有关系。时间复杂度小于O(n^4),对于本题完全能过。

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;int con[105][105],flag;int a[105][105];int n;void init(){     freopen("control.in","r",stdin);     freopen("control.out","w",stdout);}void readdata(){    int x,y,z;     scanf("%d",&n);    for (int i=1;i<=n;i++)     {        scanf("%d%d%d",&x,&y,&z);        a[x][y]=z;    }}void work(){    for (int i=1;i<=100;i++)    {        flag=1;        while (flag)//每次添加新的控制关系,则要再更新所有关系        {            flag=0;            for (int j=1;j<=100;j++)            if (a[i][j]>50&&!con[i][j]) //如果i能控制j,且没有更新过            {                flag=1;                for (int k=1;k<=100;k++) //更新a[i][k]为其控制的j占有所有公司k的股份和                {                    a[i][k]+=a[j][k];                    if (a[i][k]>100) a[i][k]=100;                }                con[i][j]=1;//更新i控制j            }        }    }        flag=1;    for (int i=1;i<=100;i++)     for (int j=1;j<=100;j++)     if (con[i][j]&&i!=j)     {         flag=0;         printf("%d %d\n",i,j);     }          if(flag)printf("0\n");}int main(){    init();    readdata();    work();    return 0;}
0 1