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); }