bzoj1412最小割

太羞耻了,m n写反了(主要是样例n m相等)

建图方法比较高(ji)端(chu),对于可以加栅栏的地方连上1的边,然后求最小割即可

为了让代码优(suo)美(duan),我写了一个check,避免多次重复的时候犯错(简直是我这种mn都能打反的人必备)

 1 #include <cstdio>
 2 #define INF 2147483647
 3 int n,m,N=1,h,t,zl,ans;
 4 int a[101][101],fir[10100],d[10100],to[100000],flo[100000],nex[100000],l[10100];
 5 inline void add(int x,int y,int z){    to[++N]=y;flo[N]=z;nex[N]=fir[x];fir[x]=N;
 6                                     to[++N]=x;flo[N]=0;nex[N]=fir[y];fir[y]=N;}
 7 inline int min(int x,int y){    return(x<y)?x:y;}
 8 inline void check(int x,int y,int X,int Y)
 9 {
10     if(X==0 || Y==0 || X>n || Y>m) return;
11     if(a[x][y]!=2 && a[X][Y]!=1)    add((x-1)*m+y,(X-1)*m+Y,1); 
12 }
13 bool bfs()
14 {
15     for(int i=1;i<=n*m+1;i++) d[i]=0;
16     for(h=1,t=1,l[1]=0,d[0]=1;h<=t;h++)
17         for(int i=fir[l[h]];i;i=nex[i])
18             if(!d[to[i]] && flo[i])
19                 l[++t]=to[i],d[l[t]]=d[l[h]]+1;
20     return d[n*m+1];
21 }
22 int dfs(int now,int flow,int sum)
23 {
24     if(now==n*m+1)    return flow;
25     for(int i=fir[now];i && (sum<flow);i=nex[i])
26     if(d[to[i]]==d[now]+1 && flo[i])
27         zl=dfs(to[i],min(flow-sum,flo[i]),0),sum+=zl,flo[i]-=zl,flo[i^1]+=zl;
28     if(sum==0) d[now]=0;
29     return sum;
30 }
31 int main()
32 {
33     scanf("%d%d",&n,&m);
34     for(int i=1;i<=n;i++)
35         for(int j=1;j<=m;j++)
36         {
37             scanf("%d",&a[i][j]);
38             if(a[i][j]==1) add(0,(i-1)*m+j,INF);
39             if(a[i][j]==2) add((i-1)*m+j,n*m+1,INF);
40         }
41     for(int i=1;i<=n;i++)
42         for(int j=1;j<=m;j++)
43             check(i,j,i-1,j),check(i,j,i+1,j),check(i,j,i,j-1),check(i,j,i,j+1);
44     for(ans=0;bfs();ans+=dfs(0,INF,0));
45     printf("%d
",ans);
46     return 0;
47 }

让我好好想想最近在犯什么错:

1.%d多打或少打

2.输入顺序没看清

3.行数和列数没分清

人生无望。。。我还是滚回普及组去吧

原文地址:https://www.cnblogs.com/wanglichao/p/5823485.html