现在经常发现原来做过的一些OJ的月赛题,与某些经典题有着很深的渊源...
有向图中,若对于任意点对i和j都有边(i,j)或边(j,i),则该有向图为竞赛图。而竞赛图的哈密顿路一定存在,因此[TOJ]1151最少的重启次数一定是1,[ZOJ]3332中没有impossible的情况。
思路是:任取一点作起点,然后逐个添加其他点。如果要把点x添加到已经连好的部分路径中,那么:
1.对于路径的第一个点a,若有边x->a,就把x加在路径首,如果没有,
2.对于路径的最后一个点b,若有边b->x,就把x加在路径末尾,如果没有
3.在路径a1
,a2
...ak
中必能找到一个位置m,同时存在边am
->x和x->am+1
,插入之!
虽然我的代码效率不高(1151有两个0.00s的!),好歹也是第一次自己写的链表~
我先写的是[ZOJ]3332
Run ID | Submit Time | Judge Status | Problem ID | Language | Run Time(ms) | Run Memory(KB) | User Name |
2170954 | 2010-04-20 20:45:12 | Accepted | 3332 | C++ | 110 | 184 | TJRAC_ACMercy(紫薇) |
发现[TOJ]1151与其类似后,果断修改!
Show Code - Run ID 929267
Submit Time:
2010-07-13 20:51:53 Language:
GNU C++ Result:
Accepted
Pid:
1151
Time:
0.61 sec. Memory:
2184 K. Code Length:
1.4 K.
while(scanf("%d",&n)!=EOF){
memset(f,0,sizeof(f));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%d",&t);
if(t) f[i+1][j+1]=1;
}
}
printf("1/n%d/n",n);
if(n==1) {printf("1/n");continue;}
first=new node;
first->next=NULL;
first->no=1;
for(i=2;i<=n;i++){
flag=1;
newnode=new node;
newnode->no=i;
if(f[i][first->no]){
newnode->next=first;
first=newnode;
flag=0;
}
if(flag){
list=first;
while(list->next!=NULL&&flag){
if(f[list->no][i]&&f[i][list->next->no]){
newnode->next=list->next;
list->next=newnode;
flag=0;
}
list=list->next;
}
if(flag&&f[list->no][i]) {
newnode->next=NULL;
list->next=newnode;
}
}
}
while(first->next!=NULL){
printf("%d ",first->no);
first=first->next;
}
printf("%d/n",first->no);
}
//system("pause");
return 0;
}