↑虽然不是我写的但是观摩一下总是没问题的嗯
看到晗神学的是神奇的ek算法.
但是看起来还是Ford-Fulkerson比较简单..所以我就学了这个...嗯其他的先看看..这个似乎比较好上手....
从题目要求来看,我们只需要建一个双向图,然后用神奇的网络流算法算出到终点的最大流量-1即可 ( 因为留一条路出来就可以满足来回不能只经过每个土地1次或者0次 )
但是并不对
如上为本题某数据 ( 好像是in3 ) 的建图[我知道我画的很丑],所示从1到7的流为2,但是放狗数为0,说明这个建图太naive了,报道出了偏差;
很明显,这个建法错误的原因是点4被经过了两次,但是事实上每个点只能经过一次,普通的建图并不能完成这个要求;
(少写一个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 ",ans); 90 } 91 else 92 printf("%d ",ans-1); 93 return 0; 94 }