【图论】[USACO]控制公司 Controlling Companies
玄妙的搜索
题目描述
有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分。(此处略去一句废话)据说,如果至少满足了以下三个条件之一,公司A就可以控制公司B了:
公司A = 公司B。
公司A拥有大于50%的公司B的股票。
公司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%的股份。
输出格式:
输出零个或更多个的控制其他公司的公司。每行包括两个整数A、B,表示A公司控制了B公司。将输出的数对以升序排列。
请不要输出控制自己的公司(应该是不输出自己,互相控制的公司还是要输出的)。
实际上我觉得这道题还是挺不错的,不过这个题面真是好生奇怪……网络上也找不到usaco的英文题面(官网上要求每一个section顺序做过去……)
大体就是搜索,然后这里的搜索在处理上还是需要一定思考的。因为如果搜索顺序不当会使得部分股份被一组关系复杂的公司重复累加。
做这题时候test9老是出锅……网上很多人都说“一个编号对应的公司不是唯一的”?这是什么意思啊……
这是WA掉的
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct node 4 { 5 int a,b; 6 }; 7 int n,tot,mp[1003][1003]; 8 bool vis[1003]; 9 node ss[10003]; 10 bool cmp(node a, node b) 11 { 12 if (a.a==b.a)return a.b<b.b; 13 return a.a<b.a; 14 } 15 void dfs(int x) 16 { 17 if (vis[x])return; 18 bool visp[1003]; 19 memset(visp, 0, sizeof(visp)); 20 visp[x] = 1;vis[x] = 1; 21 int s = 0; 22 for (int i=1; i<=1000; i++) 23 if (!visp[i]&&mp[x][i]>50){s=i;break;} 24 while (s) 25 { 26 visp[s] = 1; 27 for (int i=1; i<=1000; i++) 28 mp[x][i]+=mp[s][i]; 29 ss[++tot].a=x;ss[tot].b=s; 30 dfs(s); 31 s = 0; 32 for (int i=1; i<=1000; i++) 33 if (!visp[i]&&mp[x][i]>50){s=i;break;} 34 } 35 return; 36 } 37 int main() 38 { 39 scanf("%d",&n); 40 // freopen("lg1475.out","w",stdout); 41 for (int i=1; i<=n; i++) 42 { 43 int x,y,z; 44 scanf("%d%d%d",&x,&y,&z); 45 mp[x][y] = z; 46 } 47 for (int i=1; i<=100; i++)if (!vis[i])dfs(i); 48 sort(ss+1, ss+tot+1, cmp); 49 for (int i=1; i<=tot; i++)printf("%d %d\n",ss[i].a,ss[i].b); 50 return 0; 51 }
这就AC了
#include<bits/stdc++.h> using namespace std; struct node { int a,b; }; int n,tot,mp[103][103]; bool vis[103][103]; node ss[10003]; bool cmp(node a, node b) { if (a.a==b.a)return a.b<b.b; return a.a<b.a; } void dfs(int x, int y) { if (vis[x][y])return; vis[x][y] = 1; if (x!=y){ ss[++tot].a = x; ss[tot].b = y; } for (int i=1; i<=100; i++) { mp[x][i] += mp[y][i]; if (mp[x][i]>50)dfs(x, i); } return; } int main() { scanf("%d",&n); for (int i=1; i<=n; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); mp[x][y] = z; } for (int i=1; i<=100; i++) for (int j=1; j<=100; j++) if (mp[i][j]>50)dfs(i, j); sort(ss+1, ss+tot+1, cmp); for (int i=1; i<=tot; i++)printf("%d %d\n",ss[i].a,ss[i].b); return 0; }
以上,先存着