• 停课集训 11.28


      网络流刷题日

      1.洛谷1343地震逃生

      先复习了一波dinic,随便写了个程序

      

      很裸的题目啊,直接建图maxflow再除一除。

      

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<queue>
     6 #define ll long long
     7 #define N 205
     8 using namespace std;
     9 int n,m,x,tot,hd[N],cur[N],vis[N],d[N];
    10 struct edge{int v,next,flow,cap;}e[N*20];
    11 
    12 void adde(int u,int v,int c){
    13     e[tot].v=v;
    14     e[tot].cap=c;
    15     e[tot].next=hd[u];
    16     hd[u]=tot++;
    17 }
    18 
    19 bool bfs(){
    20     queue<int>q;
    21     memset(vis,0,sizeof(vis));
    22     q.push(1);d[1]=0;vis[1]=1;
    23     while(!q.empty()){
    24         int u=q.front();q.pop();
    25         for(int i=hd[u];~i;i=e[i].next){
    26             int v=e[i].v;
    27             if(e[i].cap-e[i].flow<=0||vis[v])continue;
    28             d[v]=d[u]+1;vis[v]=1;
    29             q.push(v);
    30         }
    31     }
    32     return vis[n];
    33 }
    34 int dfs(int u,int a){
    35     if(!a||u==n)return a;
    36     int flow=0,f;
    37     for(int &i=cur[u];~i;i=e[i].next){
    38         int v=e[i].v;
    39         if(d[u]+1==d[v]&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
    40             e[i].flow+=f;
    41             e[i^1].flow-=f;
    42             flow+=f;a-=f;
    43             if(!a)break;
    44         }
    45     }
    46     return flow;
    47 }
    48 
    49 int main(){
    50     //freopen(".in","r",stdin);
    51     //freopen(".out","w",stdout);
    52     memset(hd,-1,sizeof(hd));
    53     scanf("%d%d%d",&n,&m,&x);
    54     for(int i=1;i<=m;i++){
    55         int a,b,c;
    56         scanf("%d%d%d",&a,&b,&c);
    57         adde(a,b,c);adde(b,a,0);
    58     }
    59     int a1=0,a2=0;
    60     while(bfs()){
    61         for(int i=1;i<=n;i++)cur[i]=hd[i];
    62         a1+=dfs(1,2147483647);
    63     }
    64     if(!a1){
    65         printf("Orz Ni Jinan Saint Cow!");
    66         return 0;
    67     }
    68     if(x%a1)a2=x/a1+1;
    69     else a2=x/a1;
    70     printf("%d %d",a1,a2);
    71     return 0;
    72 }
    View Code

      

      2. 洛谷1251餐巾纸问题

       然后学习了一下zkw费用流,大概就是用dinic跑费用流,,快的飞起

      

      建图还很麻烦。把每天拆成ai,bi两点,ai表示用过的,bi没用过。建立超级源汇S,T。

      (1)S向ai连容量r[i],费用0的边,S向bi连容量r[i],费用p的边

      (2)bi向T连容量r[i],费用0的边

      (3)ai向b(i+m)连容量无穷,费用f的边,ai向b(i+n)连容量无穷,费用f的边,ai向a(i+1)连容量无穷费用0的边

      然后zkw 50ms过了

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<queue>
     6 #define ll long long
     7 #define inf 0x3f3f3f3f
     8 #define N 2005
     9 using namespace std;
    10 int day,n,m,p,s,f,S,T,tot,r[N],cur[N<<1],hd[N<<1],vis[N<<1],d[N<<1]; 
    11 ll cost;
    12 struct edge{int u,v,w,next,cap,flow;}e[N<<4];
    13 void adde(int u,int v,int w,int c){
    14     e[tot].u=u;
    15     e[tot].v=v;
    16     e[tot].w=w;
    17     e[tot].cap=c;
    18     e[tot].next=hd[u];
    19     hd[u]=tot++;
    20 }
    21 
    22 bool spfa(){
    23     memset(d,0x3f,sizeof(d));
    24     memset(vis,0,sizeof(vis));
    25     deque<int>q;d[T]=0;q.push_back(T);
    26     while(!q.empty()){
    27         int u=q.front();q.pop_front();vis[u]=0;
    28         for(int i=hd[u];~i;i=e[i].next){
    29             if(e[i^1].cap<=e[i^1].flow)continue;
    30             int w=e[i^1].w,v=e[i].v;
    31             if(d[v]>d[u]+w){
    32                 d[v]=d[u]+w;
    33                 if(vis[v])continue;
    34                 vis[v]=1;
    35                 if(!q.empty()&&d[v]<d[q.front()])q.push_front(v);
    36                 else q.push_back(v);
    37             }
    38         }
    39     }
    40     return d[S]<0x3f3f3f3f;
    41 }
    42 
    43 int dfs(int u,int a){
    44     if(!a||u==T)return a;
    45     vis[u]=1;int f=0,fl=0;
    46     for(int &i=cur[u];~i;i=e[i].next){
    47         int v=e[i].v;
    48         if(d[v]+e[i].w==d[u]&&!vis[v]&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
    49             cost+=(ll)f*e[i].w;fl+=f;
    50             e[i].flow+=f;
    51             e[i^1].flow-=f;
    52             a-=f;
    53             if(!a)break;
    54         }
    55     }
    56     vis[u]=0;return fl;
    57 }
    58 
    59 int main(){
    60 #ifdef wsy
    61     freopen("data.in","r",stdin);
    62 #else
    63     //freopen(".in","r",stdin);
    64     //freopen(".out","w",stdout);
    65 #endif
    66     memset(hd,-1,sizeof(hd));
    67     scanf("%d",&day);S=0;T=(day<<1)+1;
    68     for(int i=1;i<=day;i++)scanf("%d",&r[i]);
    69     scanf("%d%d%d%d%d",&p,&m,&f,&n,&s);
    70     for(register int i=1;i<=day;i++){
    71         adde(S,i,0,r[i]);adde(i,S,0,0);
    72         adde(S,i+day,p,inf);adde(i+day,S,-p,0);
    73         if(i!=day)adde(i,i+1,0,inf),adde(i+1,i,0,0);
    74         adde(i+day,T,0,r[i]);adde(T,i+day,0,0);
    75         if(i+m<=day)adde(i,i+day+m,f,inf),adde(i+day+m,i,-f,0);
    76         if(i+n<=day)adde(i,i+day+n,s,inf),adde(i+day+n,i,-s,0);
    77     }
    78     while(spfa()){
    79         for(int i=S;i<=T;i++)cur[i]=hd[i];
    80         dfs(S,inf);
    81     }
    82     printf("%lld",cost);
    83     return 0;
    84 }
    View Code

      

      3.bzoj1433假期的宿舍

      我的方法跟网上其他博客有点不一样,随便YY的。把每个人拆成2个点ai bi,建立超级源汇S,T。

      (1)S向所有 外校人员的ai建立容量1的边

      (2)所有 在校的要回家的学生的bi向T连容量为1的边

      (3)对于一对相互认识的人bi->aj互相建容量无穷边

      (4)每个人的ai向bi建立容量1的边

      这样以后一个流就表示一个挪动方案

      

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<cstring>
     6 #define inf 0x3f3f3f3f
     7 #define ll long long
     8 #define N 105 
     9 using namespace std;
    10 int n,S,T,tot,cur[N],st[N],hd[N],gh[N],kn[N][N],d[N],vis[N];
    11 struct edge{int v,next,cap,flow;}e[N*N*4];
    12 void adde(int u,int v,int c){
    13     e[tot].v=v;
    14     e[tot].next=hd[u];
    15     e[tot].cap=c;
    16     e[tot].flow=0;
    17     hd[u]=tot++;
    18 }
    19 
    20 bool bfs(){
    21     queue<int>q;
    22     memset(vis,0,sizeof(vis));
    23     q.push(S);d[S]=0;
    24     while(!q.empty()){
    25         int u=q.front();q.pop();vis[u]=1;
    26         for(int i=hd[u];~i;i=e[i].next){
    27             int v=e[i].v;
    28             if(e[i].cap<=e[i].flow||vis[v])continue;
    29             d[v]=d[u]+1;q.push(v);
    30         }
    31     }
    32     return vis[T];
    33 }
    34 
    35 int dfs(int u,int a){
    36     if(u==T||!a)return a;
    37     int fl=0,f;
    38     for(int i=hd[u];~i;i=e[i].next){
    39         int v=e[i].v;
    40         if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
    41             fl+=f;a-=f;
    42             e[i].flow+=f;
    43             e[i^1].flow-=f;
    44             if(a<=0)break;
    45         }
    46     }
    47     return fl;
    48 }
    49 int main(){
    50 #ifdef wsy
    51     freopen("data.in","r",stdin);
    52 #else
    53     //freopen(".in","r",stdin);
    54     //freopen(".out","w",stdout);
    55 #endif
    56     int cas;scanf("%d",&cas);
    57     while(cas--){
    58         scanf("%d",&n);S=0;T=2*n+1;tot=0;
    59         memset(hd,-1,sizeof(hd));
    60         for(int i=1;i<=n;i++)scanf("%d",&st[i]);
    61         
    62     //    for(int i=1;i<=n;i++)if(!st[i])printf("%d ",i);puts("");
    63         
    64         for(int i=1;i<=n;i++)scanf("%d",&gh[i]);
    65         
    66     //    for(int i=1;i<=n;i++)if(st[i]&&gh[i])printf("%d ",i);puts("");
    67         
    68         for(int i=1;i<=n;i++)
    69         for(int j=1;j<=n;j++)
    70         scanf("%d",&kn[i][j]);
    71         for(int i=1;i<=n;i++){
    72             if(st[i]){
    73                 if(gh[i])adde(i+n,T,1),adde(T,i+n,0);
    74             }
    75             else adde(S,i,1),adde(i,S,0);
    76         }
    77         for(int i=1;i<=n;i++)
    78         for(int j=i+1;j<=n;j++){
    79             if(!kn[i][j])continue;
    80         //    printf("%d %d
    ",i,j);
    81             int f1=st[i],f2=st[j];
    82             if(f1)adde(j+n,i,inf),adde(i,j+n,0);
    83             if(f2)adde(i+n,j,inf),adde(j,i+n,0);
    84         }
    85         for(int i=1;i<=n;i++)
    86         adde(i,i+n,1),adde(i+n,i,0);
    87         while(bfs()){
    88             for(int i=S;i<=T;i++)cur[i]=hd[i];
    89             dfs(S,0x3f3f3f3f);
    90         }
    91         int fg=0;
    92         for(int i=hd[S];~i;i=e[i].next)
    93         if(e[i].cap-e[i].flow>0)fg=1;
    94         if(fg)puts("T_T");
    95         else puts("^_^");
    96     }
    97     return 0;
    98 }
    View Code

        

       4.bzoj1934Vote善意的投票

      最小割模型。

      S向1的人建容量1的边,0的人向T建容量1的边。认识的人互相建容量1的边。

      这样求出最小割后,与S相连的点集表示最终选1的人,与T相连表示选0,每条割边表示一个冲突。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<queue>
     6 #define ll long long
     7 #define N 305
     8 using namespace std;
     9 int n,m,S,T,tot,hd[N],d[N],vis[N],cur[N];
    10 struct edge{int v,next,cap,flow;}e[N*N*4];
    11 void adde(int u,int v,int c){
    12     e[tot].v=v;
    13     e[tot].next=hd[u];
    14     e[tot].cap=c;
    15     e[tot].flow=0;
    16     hd[u]=tot++;
    17 }
    18 
    19 bool bfs(){
    20     queue<int>q;
    21     memset(vis,0,sizeof(vis));
    22     q.push(S);d[S]=0;
    23     while(!q.empty()){
    24         int u=q.front();q.pop();vis[u]=1;
    25         for(int i=hd[u];~i;i=e[i].next){
    26             int v=e[i].v;
    27             if(e[i].cap<=e[i].flow||vis[v])continue;
    28             d[v]=d[u]+1;q.push(v);
    29         }
    30     }
    31     return vis[T];
    32 }
    33 
    34 int dfs(int u,int a){
    35     if(u==T||!a)return a;
    36     int fl=0,f;
    37     for(int i=hd[u];~i;i=e[i].next){
    38         int v=e[i].v;
    39         if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
    40             fl+=f;a-=f;
    41             e[i].flow+=f;
    42             e[i^1].flow-=f;
    43             if(a<=0)break;
    44         }
    45     }
    46     return fl;
    47 }
    48 int main(){
    49     scanf("%d%d",&n,&m);
    50     memset(hd,-1,sizeof(hd));
    51     S=0;T=n+1;
    52     for(int i=1;i<=n;i++){
    53         int x;
    54         scanf("%d",&x);
    55         if(x)adde(S,i,1),adde(i,S,0);
    56         else adde(i,T,1),adde(T,i,0);
    57     }
    58     for(int i=1;i<=m;i++){
    59         int a,b;
    60         scanf("%d%d",&a,&b);
    61         adde(a,b,1);adde(b,a,1);
    62     }
    63     int flow=0;
    64     while(bfs()){
    65         for(int i=S;i<=T;i++)cur[i]=hd[i];
    66         flow+=dfs(S,0x3f3f3f3f);
    67     }
    68     printf("%d",flow);
    69     return 0;
    70 }
    View Code

      5.1854: [Scoi2010]游戏

          两种解法

     

      (1)二分图

      把每个物品和属性都当成点,物品为黑部,属性白部。物品向它有的属性建边。从属性1的点开始向下匹配,匹配到不成功即为答案。

      (2)并查集

      把属性当成点,物品当成边。那对于每一条边,可以选择他两端的一个点。

      如果一个联通块是一棵大小为n的树,我们可以从其中选出n-1个点。否则可以选出所有的点。

      记录联通块是不是树和联通块内最大的属性值,合并即可。

       选点肯定是先选出小的点来构成1,2,3,4,5……所以判断当一个属性是它所在联通块最大值时,此属性为答案

      6.bzoj1066蜥蜴

       很裸的最大流啊。拆点,每个格子拆成入点和出点,入点向出点连容量为高度的边。

      S向有蜥蜴的格子入点连容量1的边,可以跳出的边界的格子出点向T连容量无穷边。如果a格可以到达b格,a的出点连b的入点,容量无穷。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #define inf 0x7fffffff
      5 using namespace std;
      6 struct data{int to,next,v;}e[500001];
      7 int r,c,d,cnt=1,ans,mp[21][21],mark[21][21],q[802],h[802],head[802];
      8 void ins(int u,int v,int w)
      9 {cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;}
     10 void insert(int u,int v,int w)
     11 {ins(u,v,w);ins(v,u,0);}
     12 bool judge(int x1,int y1,int x2,int y2)
     13 {
     14     if(((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))<=(d*d)&&mp[x1][y1]&&mp[x2][y2])return 1;
     15     return 0;
     16 }
     17 void build()
     18 {
     19      for(int x1=1;x1<=r;x1++)
     20         for(int y1=1;y1<=c;y1++)
     21            for(int x2=x1-d;x2<=x1+d;x2++)
     22               for(int y2=y1-d;y2<=y1+d;y2++)
     23      if(judge(x1,y1,x2,y2)&&(x1!=x2||y1!=y2))insert(mark[x1][y1]+400,mark[x2][y2],inf); 
     24      for(int i=1;i<=r;i++)
     25         for(int j=1;j<=c;j++)
     26            if(mp[i][j])insert(mark[i][j],mark[i][j]+400,mp[i][j]);
     27  } 
     28 bool bfs()
     29 {
     30      memset(h,-1,sizeof(h));
     31      int t=0,w=1,i,now;q[0]=h[0]=0;
     32      while(t<w)
     33      {
     34                now=q[t];t++;i=head[now];
     35                while(i)
     36                {
     37                        if(e[i].v&&h[e[i].to]==-1)
     38                        {
     39                            h[e[i].to]=h[now]+1;
     40                            q[w++]=e[i].to; 
     41                            }
     42                        i=e[i].next; 
     43                        }
     44                }
     45      if(h[801]==-1)return 0;return 1;
     46  }
     47 int dfs(int x,int f)
     48 {
     49     if(x==801)return f;
     50     int i=head[x],used=0,w;
     51     while(i)
     52     {
     53             if(e[i].v&&h[e[i].to]==h[x]+1)
     54             {
     55                 w=f-used;w=dfs(e[i].to,min(w,e[i].v));
     56                 e[i].v-=w;e[i^1].v+=w;
     57                 used+=w;if(used==f)return f;
     58                                           }
     59             i=e[i].next;
     60             }
     61     if(!used)h[x]=-1;
     62     return used;
     63 }
     64 void dinic(){while(bfs())ans-=dfs(0,inf);}
     65 int main()
     66 {
     67     scanf("%d%d%d",&r,&c,&d);
     68     char ch[21];
     69     for(int i=1;i<=r;i++)
     70     {
     71        scanf("%s",ch);
     72        for(int j=1;j<=c;j++)
     73            mp[i][j]=ch[j-1]-'0';
     74           }
     75     int tot=0;
     76     for(int i=1;i<=r;i++)
     77        for(int j=1;j<=c;j++)
     78        {tot++;mark[i][j]=tot;} 
     79     for(int i=1;i<=r;i++)
     80     {
     81        scanf("%s",ch);
     82        for(int j=1;j<=c;j++)
     83            if(ch[j-1]=='L')
     84              {insert(0,mark[i][j],1);ans++;}
     85           }
     86     for(int i=1;i<=d;i++)
     87        for(int j=d+1;j<=r-d;j++)
     88        {
     89           insert(mark[j][i]+400,801,inf);
     90           insert(mark[j][c-i+1]+400,801,inf);
     91           }
     92     for(int i=1;i<=d;i++)
     93        for(int j=1;j<=c;j++)
     94        {
     95           insert(mark[i][j]+400,801,inf);
     96           insert(mark[r-i+1][j]+400,801,inf);
     97           }
     98     build();
     99     dinic();
    100     printf("%d",ans);
    101     return 0;
    102 }
    View Code

        7.bzoj1070修车

      费用流。把车看作点,S向每辆车连容量1费用0的点。

      把每个工人拆成n个点,k点表示倒数第k个修这辆车。

      每个工人点向T连容量1费用0的边。

      每辆车向每个工人点连边,容量1,费用为k*cost,k即为这个工人倒数第k个修这辆车。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<queue>
     6 #define ll long long
     7 #define N 105
     8 using namespace std;
     9 int n,m,tot,S,T,base,t[N][N],hd[N*N],vis[N*N],d[N*N],pre[N*N],a[N*N];
    10 struct edge{int u,v,w,next,cap;}e[N*N*6];
    11 bool spfa(int &flow,int &cost){
    12     queue<int>q;
    13     memset(pre,-1,sizeof(pre));
    14     memset(d,0x3f,sizeof(d));
    15     q.push(S);d[S]=0;a[S]=0x3f3f3f3f;
    16     while(!q.empty()){
    17         int u=q.front();q.pop();
    18         vis[u]=0;
    19         for(int i=hd[u];~i;i=e[i].next){
    20             int v=e[i].v;
    21             if(e[i].cap>0&&d[v]>d[u]+e[i].w){
    22                 d[v]=d[u]+e[i].w;pre[v]=i;
    23                 a[v]=min(a[u],e[i].cap);
    24                 if(vis[v])continue;
    25                 vis[v]=1;q.push(v);
    26             }
    27         }
    28     }
    29     if(d[T]==0x3f3f3f3f)return 0;
    30     flow+=a[T];cost+=a[T]*d[T];
    31     int u=T;
    32     while(u!=S){
    33         e[pre[u]].cap-=a[T];
    34         e[pre[u]^1].cap+=a[T];
    35         u=e[pre[u]].u;
    36     }
    37     return 1;
    38 }
    39 void adde(int u,int v,int w,int cap){
    40     e[tot].u=u;e[tot].next=hd[u];e[tot].v=v;
    41     e[tot].w=w;e[tot].cap=cap;hd[u]=tot++;
    42 }
    43 int get(int i,int j){return (j-1)*m+i;}
    44 void build(int i,int j,int k){
    45     adde(i+base,get(j,k),k*t[j][i],1);
    46     adde(get(j,k),i+base,-k*t[j][i],0);
    47 //    printf("%d %d %d
    ",i+base,get(j,k),k*t[j][i]);
    48 } 
    49 int main(){
    50     scanf("%d%d",&m,&n);
    51     memset(hd,-1,sizeof(hd));
    52     base=n*m;S=0;T=base+n+1;
    53     for(int i=1;i<=n;i++)
    54     for(int j=1;j<=m;j++)scanf("%d",&t[j][i]);    
    55     for(int i=1;i<=n;i++)adde(S,i+base,0,1),adde(i+base,S,0,0)/*printf("%d %d 0
    ",S,i+base)*/;
    56     for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
    57     for(int k=1;k<=n;k++)build(i,j,k);
    58     for(int i=1;i<=base;i++)adde(i,T,0,1),adde(T,i,0,0)/*printf("%d %d 0
    ",i,T)*/;
    59     int flow=0,cost=0;
    60     while(spfa(flow,cost));
    61     printf("%.2lf",(double)cost/n);
    62     return 0;
    63 }
    View Code

     

      8.bzoj1412狼和羊的故事

      很裸的最小割模型了。把狼和羊分开即可。

      S向狼连容量无穷边,羊向T连容量无穷边。

      狼向周围空地和羊连容量1的边,空地向周围空地和羊连容量1边。

      最小割后,和S连的点即表示狼的领地,与T相连的点表示羊的领地。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<queue>
     6 #define ll long long
     7 #define inf 0x3f3f3f3f
     8 #define N 105
     9 using namespace std;
    10 int n,m,S,T,tot,mp[N][N],hd[N*N],cur[N*N],d[N*N],vis[N*N];
    11 int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};
    12 struct edge{int v,cap,next;}e[N*N*8];
    13 int get(int i,int j){return (i-1)*m+j;}
    14 bool check(int i,int j){return i>=1&&i<=n&&j>=1&&j<=m;}
    15 void adde(int u,int v,int c){
    16     e[tot].v=v;
    17     e[tot].next=hd[u];
    18     e[tot].cap=c;
    19     hd[u]=tot++;
    20 }
    21 bool bfs(){
    22     queue<int>q;
    23     memset(vis,0,sizeof(vis));
    24     d[S]=0;q.push(S);vis[S]=1;
    25     while(!q.empty()){
    26         int u=q.front();q.pop();
    27         for(int i=hd[u];~i;i=e[i].next){
    28             int v=e[i].v;
    29             if(e[i].cap<=0||vis[v])continue;
    30             d[v]=d[u]+1;vis[v]=1;q.push(v);
    31         }
    32     }
    33     return vis[T];
    34 }
    35 int dfs(int u,int a){
    36     if(u==T||!a)return a;
    37     int fl=0,f;
    38     for(int &i=cur[u];~i;i=e[i].next){
    39         if(e[i].cap<=0)continue;
    40         int v=e[i].v;
    41         if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].cap)))){
    42             fl+=f;a-=f;e[i].cap-=f;
    43             e[i^1].cap+=f;if(!a)break;
    44         }
    45     }
    46     return fl;
    47 }
    48 int main(){
    49 #ifdef wsy
    50     freopen("data.in","r",stdin);
    51 #else
    52     //freopen(".in","r",stdin);
    53     //freopen(".out","w",stdout);
    54 #endif
    55     scanf("%d%d",&n,&m);
    56     memset(hd,-1,sizeof(hd));
    57     S=0;T=n*m+1;
    58     for(int i=1;i<=n;i++)
    59     for(int j=1;j<=m;j++){
    60         scanf("%d",&mp[i][j]);
    61         if(mp[i][j]==1)adde(S,get(i,j),inf),adde(get(i,j),S,0);
    62         else if(mp[i][j]==2)adde(get(i,j),T,inf),adde(T,get(i,j),0);
    63     }
    64     for(int i=1;i<=n;i++)
    65     for(int j=1;j<=m;j++){
    66         if(mp[i][j]==2)continue;
    67         int idx=get(i,j);
    68         for(int k=0;k<4;k++){
    69             int nx=i+dx[k],ny=j+dy[k];
    70             if(!check(nx,ny))continue;
    71             int nid=get(nx,ny);
    72             if(mp[i][j]==1){
    73                 if(mp[nx][ny]!=1)adde(idx,nid,1),adde(nid,idx,0);
    74             }
    75             else if(mp[nx][ny]!=1)adde(idx,nid,1),adde(nid,idx,0);
    76         }
    77     }
    78     int ans=0;
    79     while(bfs()){
    80         for(int i=S;i<=T;i++)cur[i]=hd[i];
    81         ans+=dfs(S,0x3f3f3f3f);
    82     }
    83     printf("%d",ans);
    84     return 0;
    85 }
    View Code

      

      

      

       每道题都因为一些zz错误调了很久,还真TM是愉悦的一天。

      

     

  • 相关阅读:
    C++ quick sort ascendingly and descendingly
    C++ write file and read file via fstream
    C++ optimized fibonacci algorithm
    C++ compute quick sort time cost via std::chrono which its precision can reach nanoseconds
    C++ selection sort.quick sort
    C++ quick sort
    C++ in ubuntu pop up message via notifysend command . zenity command
    C++ vector iterator std::ref(vec)
    C++使用new来创建动态数组
    C++ 使用new来分配内存
  • 原文地址:https://www.cnblogs.com/wsy01/p/7918482.html
Copyright © 2020-2023  润新知