首页 > 其他 > 详细

最小点割集(网络流) JLOI2014 镜面通道

时间:2017-02-12 18:56:22      阅读:201      评论:0      收藏:0      [点我收藏+]

【最小点割集】

图G中 删去一些点使得  ‘这些点的权值和最小‘ 且满足 ‘从点S走不到点T‘。

将G中每个点v   拆成v1,v2  add(v1,v2,val[v]);             //add就是加一条网络流有向边

对于G中每条有向边(u,v)  add(u2,v1,inf); (无向就add无向边)

源使S2 汇是T1  求最小割、

割边e(v1,v2),就是意味点v是要删去的点(当然 方案数不唯一)

【JLOI2014 镜面通道】BZOJ 3630

物理的费马小定理 通风则通光

把上下边界当成 两个矩形,

每个矩形和圆作为一个点,若两者相交则在两点间连无向边

就成最小点割集中的原图G了

上代码:

技术分享
 1 #include <bits/stdc++.h>
 2 #define M 300000
 3 #define N 700
 4 #define inf 100000000
 5 #define eps 0.000000001
 6 using namespace std;
 7 int a[M],b[M],c[M],next[M],g[N],d[N],f[N],r[305],ax[305],bx[305],ay[305],by[305],ty[305],nn,mm,n,m=1,S,T,ans;
 8 double dis(int a,int b,int c,int d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
 9 int check(int i,int j){
10     if (i==j) return 0;
11     int v=ty[i]|ty[j];
12     if (v==1){
13         if (dis(ax[i],ay[i],ax[j],ay[j])<=r[i]+r[j]+eps) return 1; 
14     }else
15     if (v==2){
16         if ((ax[i]>=ax[j]&&ax[i]<=bx[j]||bx[i]>=ax[j]&&bx[i]<=bx[j])&&(ay[j]>=ay[i]&&ay[j]<=by[i]||by[j]>=ay[i]&&by[j]<=by[i])) return 1;
17         if ((ay[i]>=ay[j]&&ay[i]<=by[j]||by[i]>=ay[j]&&by[i]<=by[j])&&(ax[j]>=ax[i]&&ax[j]<=bx[i]||bx[j]>=ax[i]&&bx[j]<=bx[i])) return 1;
18     }else{
19         if (ty[i]==2) swap (i,j);
20         if (dis(ax[i],ay[i],ax[j],ay[j])<=r[i]+eps) return 1;
21         if (dis(ax[i],ay[i],ax[j],by[j])<=r[i]+eps) return 1;
22         if (dis(ax[i],ay[i],bx[j],ay[j])<=r[i]+eps) return 1;
23         if (dis(ax[i],ay[i],bx[j],by[j])<=r[i]+eps) return 1;
24         if (ax[i]>=ax[j]&&ax[i]<=bx[j])
25         if (abs(ay[i]-ay[j])<=r[i]||abs(ay[i]-by[j])<=r[i]) return 1;
26         if (ay[i]>=ay[j]&&ay[i]<=by[j])
27         if (abs(ax[i]-ax[j])<=r[i]||abs(ax[i]-bx[j])<=r[i]) return 1;
28     } return 0;
29 }
30 void add(int i,int j,int k){
31     ++m; a[m]=i; b[m]=j; c[m]=k;
32     next[m]=g[i]; g[i]=m;
33     ++m; a[m]=j; b[m]=i; c[m]=0;
34     next[m]=g[j]; g[j]=m;
35 }
36 int spfa(){
37     for (int i=0;i<=T+1;++i)f[i]=-1;
38     d[1]=S; f[S]=0;
39     for (int l=1,r=2;l<r;++l){
40         for (int i=g[d[l]];i;i=next[i])
41             if (c[i]&&f[b[i]]==-1){
42                 f[b[i]]=f[d[l]]+1;
43                 d[r++]=b[i];
44             }
45     }
46     if (f[T]==-1) return 0; return 1;
47 }
48 int flow(int x,int ff){
49     if (x==T) return ff;
50     int use=0; int w;
51     for (int i=g[x];i;i=next[i])
52     if (c[i]&&f[b[i]]==f[x]+1){
53         w=flow(b[i],min(c[i],ff-use));
54         c[i]-=w; c[i^1]+=w; use+=w;
55         if (use==ff) return ff;
56     }
57     if (!use) f[x]=-1; return use;
58 }
59 int main(){
60     scanf("%d%d%d",&nn,&mm,&n); 
61     for (int i=1;i<=n;++i){
62         scanf("%d",&ty[i]); 
63         ty[i]==1?scanf("%d%d%d",&ax[i],&ay[i],&r[i]):
64         scanf("%d%d%d%d",&ax[i],&ay[i],&bx[i],&by[i]);
65     }
66     ty[n+1]=ty[0]=2; by[0]=ay[0]=mm; bx[0]=bx[n+1]=nn;
67     for (int i=0;i<=n+1;++i){
68         for (int j=0;j<=n+1;++j)
69         if (check(i,j)) add(i<<1|1,j<<1,inf); 
70     }
71     for (int i=1;i<=n;++i){
72         add(i<<1|1,i<<1,1);
73         add(i<<1,i<<1|1,1);
74     }
75     S=1; T=n+1<<1;
76     while (spfa()) ans+=flow(S,inf);
77     printf("%d",ans);
78     return 0;
79 }
View Code

 

最小点割集(网络流) JLOI2014 镜面通道

原文:http://www.cnblogs.com/cyz666/p/6391453.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!