USACO Controlling Companies

1、本题用dfs做,刚开始我觉得困难的原因是觉得公司之间的控制关系非常复杂,纵横交错。实际上应该一个一个地算,各个击破,每次只考虑一个公司及其子公司。如果一个公司没有直接控制任何子公司,它不可能间接控制任何公司。注意要引入一个con数组来记录dfs所施加的影响(很关键,因为不可能同时知道哪些A的子公司控制B公司,只能找到一个就在B上累加一次,一旦超过50,B就成为A的子公司了)。

2、本题错误次数比较多,因为数据有点不自然,不是公司的编号为1-n这么方便,而是1-100内的n个任意数,所以说,用邻接矩阵不现实,要用邻接表来表示,还要非常仔细避免出错。

/*
ID:mrxy564
PROG:concom
LANG:C++
*/
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX=105;
struct node{
    int num;
 int stock;
}G[110][110];
int con[110][110];
bool vis[110];
int n,a,b;
void dfs(int boss,int num){
 vis[num]=true;
    for(int i=1;i<=G[num][0].num;i++){
  int temp=G[num][i].num;
  con[boss][temp]+=G[num][i].stock;
  if(con[boss][temp]>50&&!vis[temp]) dfs(boss,temp);
 }
 return;
}
int main(){
 freopen("concom.in","r",stdin);
 freopen("concom.out","w",stdout);
 scanf("%d",&n);
 memset(con,0,sizeof(con));
 memset(G,0,sizeof(G));
 for(int i=0;i<n;i++){
     scanf("%d%d",&a,&b);
  scanf("%d",&G[a-1][++G[a-1][0].num].stock);
  G[a-1][G[a-1][0].num].num=b-1;
 }
    for(int i=0;i<MAX;i++){
  if(G[i][0].num>0){
   memset(vis,false,sizeof(vis));
         dfs(i,i);
  }
 }
 for(int i=0;i<MAX;i++)
  for(int j=0;j<MAX;j++)
   if(con[i][j]>50&&i!=j) printf("%d %d\n",i+1,j+1);
 return 0;
}

官方题解:

The method used here to solve the problem is as follows. We keep track of which companies control which other companies, and every time we hear that so and so owns this much percent of so and so, we update our information.

The array "owns" keeps track of how much of company j is owned by company i, whether directly or via controlled companies. The array "controls" keeps track of which companies are controlled by which other companies.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define NCOM 101

int owns[NCOM][NCOM];        /* [i,j]: how much of j do i and its
                                controlled companies own? */
int controls[NCOM][NCOM];    /* [i, j]: does i control j? */

/* update info: now i controls j */
void
addcontroller(int i, int j)
{
    int k;

    if(controls[i][j])        /* already knew that */
        return;

    controls[i][j] = 1;

    /* now that i controls j, add to i's holdings everything from j */
    for(k=0; k<NCOM; k++)
        owns[i][k] += owns[j][k];

    /* record the fact that controllers of i now control j */
    for(k=0; k<NCOM; k++)
        if(controls[k][i])
            addcontroller(k, j);

    /* if i now controls more companies, record that fact */
    for(k=0; k<NCOM; k++)
        if(owns[i][k] > 50)
            addcontroller(i, k);
}

/* update info: i owns p% of j */
void
addowner(int i, int j, int p)
{
    int k;

    /* add p% of j to each controller of i */
    for(k=0; k<NCOM; k++)
        if(controls[k][i])
            owns[k][j] += p;

    /* look for new controllers of j */
    for(k=0; k<NCOM; k++)
        if(owns[k][j] > 50)
            addcontroller(k, j);
}

void
main(void)
{
    FILE *fin, *fout;
    int i, j, n, a, b, p;

    fin = fopen("concom.in", "r");
    fout = fopen("concom.out", "w");
    assert(fin != NULL && fout != NULL);

    for(i=0; i<NCOM; i++)
        controls[i][i] = 1;

    fscanf(fin, "%d", &n);
    for(i=0; i<n; i++) {
        fscanf(fin, "%d %d %d", &a, &b, &p);
        addowner(a, b, p);
    }

    for(i=0; i<NCOM; i++)
    for(j=0; j<NCOM; j++)
        if(i != j && controls[i][j])
            fprintf(fout, "%d %d\n", i, j);
    exit(0);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值