[NKU]sweet @ Google && TopCoder && CodeForces

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  33 Posts :: 1 Stories :: 15 Comments :: 0 Trackbacks
昨天在老图,借得一本随机算法的书,乍一看目录,卧槽,NB了,什么都能随机……果断借走……
第一章介绍了蒙特卡罗算法和拉斯维加斯算法,Qsort就是拉斯维加斯算法,随机的结果只影响程序速度;而下面这个题,无源无汇的最小割,则是蒙特卡罗算法……随机的结果都不见得对,但是,多随机几次,得到最优解的概率会增大不少

算法很简单,在图中随机选择一条边,并将他们连接的顶点(顶点集合更为妥当……)合并,直到只剩下两个顶点集合,则这两个集合间的边至少是个割………多次随机则应该就能得到最小割了……
每次得到最小割的概率,书上证明是 2/n^2 ,可以说是相当之小……利用高等数学的知识,找不到的概率应该是1-2/n^2,于是乎,执行N^2/2次,还找不到答案的概率就是1/e……而每次随机一条边大概是O(M)的级别吧……整个算法大概是O(n*n*m)的(确切说是omega,一定是这么多次),还不保证对……

想起AC哥说过,去年FZU的B,HDU3691是这么个题,于是搞了搞,轻松拍完,样例无压力过了……之后各种TLE……毕竟300*300*50000还是压力较大的……然后各种调整随机次数,期间翻译至java……仍然TLE……一怒之下,把随机次数调整成了N次,至少能WA了……C++版本需要2400+MS,java版本需要1700+MS……(java版程序套用了我的java模板,IO是类似getchar的优化,C++是scanf,可见数据之WS……)于是把java版程序的随机次数改成5*N次,居然过了……

现在想来,数据可能水了;也可能书上理论证明的时候,放缩的太厉害,然后几百次方之后,正确率实际上比理论计算会高出很多……
无代码无真相

  1 import java.util.*;
  2 import java.io.*;
  3 import java.math.*;
  4 
  5 
  6 public class HDU3691 {
  7     public static void main(String args[]) throws IOException {
  8         new Prob().solve();
  9     }
 10 }
 11 
 12 class Prob {
 13     int[] f = new int[50010];
 14     int[] t = new int[50010];
 15     int[] c = new int[50010];
 16     int[] fa = new int[310];
 17     int n,m,tot;
 18     int ans;
 19     Random rand = new Random();
 20     
 21     int find(int x) {
 22         if (x == fa[x]) return x;
 23         return fa[x] = find(fa[x]);
 24     }
 25 
 26     void change(int x,int y) {
 27         x = find(x);
 28         y = find(y);
 29         fa[x] = y;
 30     }
 31     
 32     int work() {
 33         for (int i = 1; i <= n; i++) {
 34             fa[i] = i;
 35         }
 36         int cnt = n;
 37         while (cnt > 2) {
 38             int now = rand.nextInt(tot);
 39             if (find(f[now]) == find(t[now])) {
 40                 int tmp = f[now]; f[now] = f[tot-1]; f[tot-1= tmp;
 41                 tmp = t[now]; t[now] = t[tot-1]; t[tot-1= tmp;
 42                 tmp = c[now]; c[now] = c[tot-1]; c[tot-1= tmp;
 43                 tot --;
 44             } else {
 45                 cnt --;
 46                 change(f[now],t[now]);
 47             }
 48         }
 49         int ans = 0;
 50         for (int i = 0; i < m; i++) {
 51             if (find(f[i])!=find(t[i])) {
 52                 ans += c[i];
 53             }
 54         }
 55         return ans;
 56     }
 57 
 58     final int TIMES = 5;    
 59     
 60     void solve() throws IOException {
 61         MyReader in = new MyReader();
 62         for (;;) {
 63             n = in.nextInt();
 64             m = in.nextInt();
 65             tot = in.nextInt();
 66             if (n + m + tot == 0break;
 67             for (int i = 0; i < m; i++) {
 68                 f[i] = in.nextInt();
 69                 t[i] = in.nextInt();
 70                 c[i] = in.nextInt();
 71             }
 72             ans = 0x7fffffff;
 73             int times = TIMES * n;
 74             while (times-- > 0) {
 75                 tot = m;
 76                 int tmp = work();
 77                 if (tmp < ans) {
 78                     ans = tmp;
 79                 }
 80             }
 81             System.out.println(ans);
 82         }
 83     }
 84     void debug(Objectx) {
 85         System.out.println(Arrays.deepToString(x));
 86     }
 87 }
 88 
 89 class MyReader {
 90     BufferedReader br = new BufferedReader (
 91             new InputStreamReader (System.in));
 92     StringTokenizer in;
 93     String next() throws IOException {
 94         if (in == null || !in.hasMoreTokens()) {
 95             in = new StringTokenizer(br.readLine());
 96         }
 97         return in.nextToken();
 98     }
 99     int nextInt() throws IOException {
100         return Integer.parseInt(next());
101     }
102 }


posted on 2011-04-02 14:00 sweetsc 阅读(462) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: