网络流小结+[jzyzoj p1320] patrol

一个不能更清楚的网络流介绍

↑虽然不是我写的但是观摩一下总是没问题的嗯
 
看到晗神学的是神奇的ek算法.
但是看起来还是Ford-Fulkerson比较简单..所以我就学了这个...嗯其他的先看看..这个似乎比较好上手....
 
从题目要求来看,我们只需要建一个双向图,然后用神奇的网络流算法算出到终点的最大流量-1即可 ( 因为留一条路出来就可以满足来回不能只经过每个土地1次或者0次 )
 但是并不对
 
网络流小结+[jzyzoj p1320] patrol - 拟南芥 - 鲸头鹳
 
如上为本题某数据 ( 好像是in3 ) 的建图[我知道我画的很丑],所示从1到7的流为2,但是放狗数为0,说明这个建图太naive了,报道出了偏差;
很明显,这个建法错误的原因是点4被经过了两次,但是事实上每个点只能经过一次,普通的建图并不能完成这个要求;
我们需要的是限制每个点的流量,那么我们把每个点变成流量为1的边 参考晗神博客 )如下图
网络流小结+[jzyzoj p1320] patrol - 拟南芥 - 鲸头鹳
 
(少写一个4假装没看见好了,最后的7看起来很像1就像吧..)
这些点i与i+n相连的边,边权都为1,这样就做到了每个"点"经过一次,起点和终点不需要流量限制所以注意特判
 
所以最恶心的是为什么我完全没考虑每个点的流量就能写90分???????滔天的水扑面而来啊摔
顺便存一个丑代码
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<cstdlib>
 7 using namespace std;
 8 const int minf=2100010000;
 9 int n,m;
10 struct nod{
11     int rev;
12     int y;
13     int next;
14     int v;
15 }e[201010];
16 int head[2100]={};
17 int tot=0;
18 bool vis[2100]={};
19 inline void init(int x,int y,int v,int rev){
20     e[++tot].y=y;
21     e[tot].next=head[x];
22     e[tot].v=v;
23     e[tot].rev=rev;
24     head[x]=tot;
25 }
26 inline int dis(int x){
27     return x+n;
28 }
29 int dfs(int s,int t,int f){
30     if(s==t){
31         return f;
32     }
33     vis[s]=1;
34     for(int i=head[s];i;i=e[i].next){
35         int v=e[i].v,y=e[i].y;
36         if(vis[y]==0&&v>0){
37             int d=dfs(y,t,min(f,v));
38             if(d>0){
39                 e[i].v-=d;
40                 e[e[i].rev].v+=d;
41                 return d;
42             }
43         }
44     }
45     return 0;
46 }
47 int main(){
48     //freopen("wtf.in","r",stdin);
49     scanf("%d%d",&n,&m);
50     int x,y;
51     for(int i=2;i<n;i++){
52         init(i,i+n,1,tot+2);
53         init(i+n,i,1,tot);
54     }
55     for(int i=1;i<=m;i++){
56         scanf("%d%d",&x,&y);
57         if(x>y){
58             swap(x,y);
59         }
60         if(y==n){
61             init(x+n,y,1,tot+2);
62             init(y,x+n,0,tot);
63             init(y,x+n,1,tot+2);
64             init(x+n,y,0,tot);
65         }
66         else if(x==1){
67             init(1,y,1,tot+2);
68             init(y,1,0,tot);
69             init(y,1,1,tot+2);
70             init(1,y,0,tot);
71         }
72         else{
73             init(x+n,y,1,tot+2);
74             init(y,x+n,0,tot);
75             init(y+n,x,1,tot+2);
76             init(x,y+n,0,tot);
77         }
78     }
79     int ans=0;
80     for(;;){
81         memset(vis,0,sizeof(vis));
82         int f=dfs(1,n,minf);
83         if(f==0){
84             break;
85         }
86         ans+=f;
87     }
88     if(ans==0){
89         printf("%d\n",ans);
90     }
91     else
92         printf("%d\n",ans-1);
93     return 0;
94 }
View Code

 

posted @ 2017-11-04 16:57  鲸头鹳  阅读(170)  评论(0编辑  收藏  举报