POJ 3155 Hard Life 最大密度子图 最大权闭合图 网络流 二分

http://poj.org/problem?id=3155

最大密度子图和最大权闭合图性质很相近(大概可以这么说吧),一个是取最多的边一个是取最多有正贡献的点,而且都是有选一种必须选另一种的限制,一个是选边必须选其两边的点,一个是选正权点必须选其相邻的负权点。

那么就可以把最大密度子图用最大权闭合图相近的方式写,二分+网络流就可以了,网络流建图方法可以参考我上一篇博客。

https://blog.csdn.net/power721/article/details/6781518 也就是该博客的第一种做法,不写第二种因为我懒,over。

顺便我的写法设置的精度单位(随便叫了个名字,领会精神)是1.0/n/n,有自环的话有点不靠谱,1e-4什么的可能逻辑上更合理一点。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<queue>
 7 using namespace std;
 8 #define LL long long
 9 const int maxn=2010;
10 const double minf=1e14;
11 const double eps=1.0/1e16;
12 int n,m,s,t;
13 LL val[maxn]={};
14 int a[maxn][2]={};
15 struct nod{
16     int y,next;double v;
17 }e[maxn*10]; int head[maxn],tot=1;
18 queue<int>q; int dep[maxn]={};
19 int zz[maxn]={},tly=0,vis[maxn]={};
20 inline void init(int x,int y,double v){
21     e[++tot].y=y;e[tot].v=v;e[tot].next=head[x];head[x]=tot;
22 }
23 bool dfs(){
24     memset(dep,0,sizeof(dep));
25     q.push(s);dep[s]=1;
26     while(!q.empty()){
27         int x=q.front();q.pop();
28         for(int i=head[x];i;i=e[i].next){
29             if(e[i].v>eps&&!dep[e[i].y]){
30                 dep[e[i].y]=dep[x]+1;
31                 q.push(e[i].y);
32             }
33         }
34     }
35     return dep[t];
36 }
37 double dfs1(int x,double fc){
38     if(x==t){
39         return fc;
40     }
41     double he=0,z;
42     for(int i=head[x];i;i=e[i].next){
43         if(dep[x]+1==dep[e[i].y]){
44             z=dfs1(e[i].y,min(fc-he,e[i].v));
45             he+=z;e[i].v-=z;e[i^1].v+=z;
46             if(fc-he<eps)break;
47         }
48     }
49     return he;
50 }
51 bool check(double v){
52     memset(head,0,sizeof(head));tot=1;
53     for(int i=1;i<=m;i++){
54         init(n+i,a[i][1],minf);init(a[i][1],n+i,0);
55         init(n+i,a[i][0],minf);init(a[i][0],n+i,0);
56         init(s,n+i,1.0);init(n+i,s,0);
57     }
58     for(int i=1;i<=n;i++){init(i,t,v);init(t,i,0);}
59     while(dfs())dfs1(s,minf);
60     for(int i=1;i<=m;i++){
61         int z=(i-1)*6+1+5;
62         if(e[z].v>eps){
63             return 1;
64         }
65     }
66     return 0;
67 }
68 void dfs2(int x){
69     if(x==t)return;
70     if(x<=n)zz[++tly]=x;
71     vis[x]=1;
72     for(int i=head[x];i;i=e[i].next){
73         if(vis[e[i].y]||e[i].v<eps)continue;
74         dfs2(e[i].y);
75     }
76 }
77 int main(){
78     scanf("%d%d",&n,&m);s=n+m+1;t=s+1;
79     if(n==0){ printf("0\n");return 0; }
80     if(m==0){ printf("1\n1\n");return 0; }
81     for(int i=1;i<=m;i++){scanf("%d%d",&a[i][0],&a[i][1]);}
82     double l=0.5,r=m,mid;r=max(r,1.0);
83     double mi=1.0/(double)n/(double)n;
84     while(r-l>mi){
85         mid=(l+r)/2;
86         if(check(mid))l=mid;
87         else r=mid;
88     }
89     check(l-mi);
90     dfs2(s);
91     printf("%d\n",tly);sort(zz+1,zz+1+tly);
92     for(int i=1;i<=tly;i++)printf("%d\n",zz[i]);
93     return 0;
94 }
View Code

 

 

 

posted @ 2018-05-29 15:51  鲸头鹳  阅读(220)  评论(0编辑  收藏  举报