POJ2531-Network Saboteur

转载请注明出处:優YoU  http://user.qzone.qq.com/289065406/blog/1303612537

题目大意:

把一个完全图分成两部分,使得连接这两部分边的权和最大。

 

解题思路:

图论的无向完全图的最大割问题 (做网络最大流的时候同学们应该看过最小割,所以别问我什么是最大割了。。。不懂的百度去。。。)

可以用 随机化算法 Random Algorithm 去做

 

一开始我没读懂题,以为是求最大权。。。傻呼呼的用最了最小生成树的算法去做= =

一直RERERE。。。还以为是数组开得不够大。。。悲剧啊。。。

 

虽然是图论,但不懂得为什么人家要把这题归类到 搜索题 去,用搜索我完全没思路去做。。。。 额,不多说,详细思路看我的程序,解释非常详尽

 1 //Memory Time
2 //188K 375MS
3
4 #include<iostream>
5 using namespace std;
6
7 const int TimeLimit=2000; //本题时间限制为2000ms
8
9 int main(int i,int j)
10 {
11 int n;
12 while(cin>>n)
13 {
14 /*Input*/
15
16 int w[30][30]={0};
17 for(i=1;i<=n;i++)
18 for(j=1;j<=n;j++)
19 {
20 cin>>w[i][j];
21 w[j][i]=w[i][j]; //双向完全图
22 }
23
24 /*Random Algorithm*/
25
26 bool subset[30]={false}; //A集:true B集:false
27 int time=TimeLimit*100; //使随机次数尽可能大,随机结果尽可能接近最优解
28 long max_w=0; //最大割的权值之和
29 long sum=0; //当前边割集权和
30
31 while(time--)
32 {
33 int x=rand()%n+1; //生成随机数 x,对应于总集合的某个结点x
34 //注意由于使用的结点序号为1~n,对应了数组下标,下标为0的数组元素没有使用
35 //那么这里必须+1,因为若rand()=n,那么再对n取模结果就为0
36 //这时就会导致使用了不存在的 [0]结点,本应使用的 [n]结点就被丢弃了
37
38 subset[x]=!subset[x]; //改变x所在的集合位置
39
40 for(int i=1;i<=n;i++) //由于是完全图,所以每个顶点i都与x相关联,因此要全部枚举
41 {
42 if(subset[i]!=subset[x]) //结点i 和 x分别在两个集合内
43 sum+=w[i][x]; //就是说因为x所在集合的改变,使得割边的个数增加
44 //割集的原权值 要加上 当前新加入的割边(i,x)的权值
45
46 if(i!=x && subset[i]==subset[x]) //结点i 和 x分别在相同的集合内,但他们不是同一元素
47 sum-=w[i][x]; //就是说因为x所在集合的改变,使得割边的个数减少
48 //割集的原权值 要减去 当前失去的割边(i,x)的权值
49 }
50
51 if(max_w < sum)
52 max_w = sum;
53 }
54
55 cout<<max_w<<endl;
56 }
57 return 0;
58 }

posted on 2011-07-31 16:48  小優YoU  阅读(301)  评论(0编辑  收藏  举报

导航