Description
早上好,特工W-12,你需要完成的以下的任务。
我们已经渗透到一个叫混乱与祸害的组织中,希望能掌握该组织的管理权。不幸的是,它们似乎已经准备好应对这样的事件了,它们使用了一个很复杂的设计分配管理权力,这使得我们的渗透工作非常艰难。
那家组织的管理系统被分成若干个单位,对于任意两个单位A和B,要么A管理B要么B管理A,同时这个管理关系可以形成环,因此可以出现A管理B、B管理C、C管理A的情况。
我们可以安排特工去渗透到任意一个单位,那将使得我们控制该单位和那个单位直接管理的单位,但是不包括间接管理的单位。比如之前的样例,渗透到A单位会让我们控制A和B,但不能控制C。
对于一个成功的渗透工作来说,我们必须要控制所有的单位才行,否则其他单位会发现我们,同时破坏我们的计划。而你也知道,我们现在从更高的部门那里拿到的经费十分紧缺,我们必须最高效地完成任务。你的任务就是要找出控制单位最少的可行方案。
Input
第一行包含一个整数n,表示该组织的单位数。接下来n行每行n个二进制位。在其中的第i行第j列位置,若为1表示i单位控制j单位,否则j单位控制i单位
Output
共一行,第一个整数ans表示最少的控制单位数量
似乎没有正常的算法,所以用随机调整,随机排列1..n,顺序扫描删去可删的点,再随机加入一个点,重复多次
#include<cstdio> #include<cstdlib> #include<algorithm> int n,ans; char s[100][100]; int ps[100],pp=0; int vs[100],stk[100],stp=0; void cal(){ stp=0; for(pp=0;pp<n;pp++)ps[pp]=pp,vs[pp]=0; for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(s[i][j])++vs[j]; for(int t=0;t<5;t++){ std::random_shuffle(ps,ps+pp); for(int i=0;i<pp;i++){ int x=ps[i]; bool ed=1; for(int j=0;j<n;j++)if(s[x][j]>=vs[j]){ed=0;break;} if(ed){ for(int j=0;j<n;j++)if(s[x][j])--vs[j]; stk[stp++]=x; ps[i--]=ps[--pp]; } } if(pp<ans)ans=pp; if(!stp)continue; int w=rand()%stp; int x=ps[pp++]=stk[w]; stk[w]=stk[stp--]; for(int i=0;i<n;i++)if(s[x][i])++vs[i]; } } int main(){ srand(1844677); int T=1; while(~scanf("%d",&n)){ for(int i=0;i<n;i++){ scanf("%s",s[i]),s[i][i]='1'; for(int j=0;j<n;j++)s[i][j]-='0'; } ans=n; for(int i=0;i<180;i++)cal(); printf("Case %d: %d\n",T,ans); T++; } return 0; }