【搜索】逛公园

来源:互联网 发布:sql数据库用户权限 编辑:程序博客网 时间:2024/04/28 02:09

逛公园

(park.pas/c/cpp/in/out)

时限:1 sec | 内存:64 MB

背景

   SC theme Park 终于开业了,可爱的平平小朋友很荣幸的成为第一个游客。

    公园设计强调,复杂就是美。scp大老板给他的公园设计了一个极其复杂的布局:

由于公园极大,而景点又很多,scp大老板在任意的两个景点之间都建造了一条星光小道,而且还为每条小道制定了方向。

 

题目描述

    现在,平平从scp大老板那里得知公园总共有N个景点,并且已经知道了每一条星光小道的方向,但由于平平的方向感极差而RP又极低,于是一旦公园中出现回路,即存在环,平平便会迷路,并且无论怎么走都走不出去。

    这样,scp大老板可就伤透脑筋了。为了使平平不会迷路,scp大老板决定改变其中M条星光小道的方向使得公园里不存在回路,但scp大老板又希望改变的小道的条数最少。由于很忙,腾不出时间,scp大老板只好请教即将参加noip的你。(注意:任意两个景点之间有且只有一条星光小道,且任意两条小道都是不相通的,即不能从一条小道不经过景点直接到达另一条小道)。

 

输入

第一行有一个整数N,表示有N个景点。

接下来是一张N*N的矩阵,第i+1行第j列表示有无从景点i指向景点j的星光小道(0表示没有,1表示有)。

 

输出

输出仅包括一行,即M的最小值。

 

输入样例 (park.in)

4

0 0 0 0

1 0 1 0

1 0 0 1

1 1 0 0

 

输出样例 (park.out)

1

 

数据规模

对于30%数据,1<=N<=10;

对于100%数据,1<=N<=20.




这套题比较难,实在没能做完。


有一个结论,完全图中如果没有环。那么我们将所有点按照出度排序,必然是0、1、2、3、4....n-1。


证明:必定有一个点出度为0,否则有环。因为是完全图,因此其他所有点必定向出度为0的点连一条边,因此出度至少为1。

而出度为1的点必定存在,否则有环。因此其它点出度至少为2。。依此类推。可证得所有点出度依次为0、1、2...n-1


此时便可以搜索。

搜索有两种思路比较清晰。

一种是我一开始采用的。TLE30。按出度升序枚举点i,每次枚举时遍历一次出度较小的点j,如果i到j无边,说明现在这条边是改变而来的的,答案加1。

另一种TLE60。按入度升序枚举点i,并把答案加上入度(这不是真正的入度,稍后说明),遍历所有的点j,如果i到j有边,则将j的入度减1,表示只记录原来没有而是新变来的入边。


TLE30:

#include <cstdio>#include <algorithm>long c = 0;long ans = 0x7f7f7f7f;char map[30][30];bool used[30];long bs[30];long stack[30];long top = 0;long n;struct node{long i;long c;bool operator<(const node& n2)const{return c<n2.c;}}chudu[30];void dfs(long nc,long c){if (nc >= ans)return;if (c == n+1){ans = ans<nc?ans:nc;return;}for (long ii=1;ii<n+1;ii++){long i = chudu[ii].i;if (!used[i]){used[i] = 1;stack[++top] = i;long tmp = 0;for (long j=1;j<c;j++){tmp += map[stack[j]][i];}dfs(nc+tmp,c+1);top --;used[i] = 0;}}}int main(){freopen("park.in","r",stdin);freopen("park.out","w",stdout);scanf("%ld",&n);for (long i=1;i<n+1;i++){chudu[i].i = i;for (long j=1;j<n+1;j++){do map[i][j] = getchar()-'0';while (map[i][j]!=0&&map[i][j]!=1);chudu[i].c += map[i][j];}}std::sort(chudu+1,chudu+n+1);dfs(0,1);printf("%ld",ans);return 0;}
TLE60:
#include <cstdio>long ans = 0;long minans = 0x7f7f7f7f;long into[60];bool used[60];char map[60][60];long n;void dfs(long u){if (u == n){minans = minans<ans?minans:ans;return;}for (long i=1;i<n+1;i++){if (!used[i]){ans += into[i];if (ans < minans){    used[i] = true;    for (long j=1;j<n+1;j++)    if (map[i][j]) into[j]--;                  dfs(u+1);        for (long j=1;j<n+1;j++)    if (map[i][j]) into[j]++;    used[i] = false;            }ans -= into[i];}}}int main(){freopen("park.in","r",stdin);freopen("park.out","w",stdout);scanf("%ld",&n);for (long i=1;i<n+1;i++){for (long j=1;j<n+1;j++){do map[i][j] = getchar() - '0';while (map[i][j]!=1&&map[i][j]!=0);if (map[i][j]){into[j]++;}}}dfs(0);printf("%ld",minans);return 0;}


原创粉丝点击