bzoj3504: [Cqoi2014]危桥(网络流)

3504: [Cqoi2014]危桥

题目:传送门 


题解:

   一开始觉得要跑四次网络流...但是想想好像两次?

   st-->a1/b1  a2/b2-->ed

   好像这样也OK?但是a1流b2或者b1流到a2怎么办?完了...又想错了。

   问了一波zzz大佬,他说我没想错...

   把b1和b2换过来再流一次的话...那原本a1流到b2的流量流到b1再流到a2那不就是相当于a1可以流到a2咯

   每次跑完都看一下流量是不是等于an+bn就好啦。

    


代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define inf 999999999
  7 using namespace std;
  8 struct node
  9 {
 10     int x,y,c,next,other;
 11 }a[210000];int len,last[110];
 12 int n,a1,a2,an,b1,b2,bn,st,ed;
 13 void ins(int x,int y,int c)
 14 {
 15     int k1,k2;
 16     k1=++len;
 17     a[len].x=x;a[len].y=y;a[len].c=c;
 18     a[len].next=last[x];last[x]=len;
 19     k2=++len;
 20     a[len].x=y;a[len].y=x;a[len].c=0;
 21     a[len].next=last[y];last[y]=len;
 22 
 23     a[k1].other=k2;
 24     a[k2].other=k1;
 25 }
 26 int list[210000],h[110],head,tail;
 27 bool bt_h()
 28 {
 29     list[1]=st;head=1;tail=2;
 30     memset(h,0,sizeof(h));
 31     h[st]=1;
 32     while(head!=tail)
 33     {
 34         int x=list[head];
 35         for(int k=last[x];k;k=a[k].next)
 36         {
 37             int y=a[k].y;
 38             if(a[k].c>0 && h[y]==0)
 39             {
 40                 h[y]=h[x]+1;
 41                 list[tail++]=y;
 42             }
 43         }
 44         head++;
 45     }
 46     if(h[ed]==0)return false;
 47     return true;
 48 }
 49 int find_flow(int x,int flow)
 50 {
 51     if(x==ed)return flow;
 52     int s=0,t;
 53     for(int k=last[x];k;k=a[k].next)
 54     {
 55         int y=a[k].y;
 56         if(h[y]==h[x]+1 && a[k].c>0 && s<flow)
 57         {
 58             s+=(t=find_flow(y,min(a[k].c,flow-s)));
 59             a[k].c-=t;a[a[k].other].c+=t;
 60         }
 61     }
 62     if(s==0)h[x]=0;
 63     return s;
 64 }
 65 char ss[55][55];
 66 int main()
 67 {
 68     while(scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF)
 69     {
 70         len=0;memset(last,0,sizeof(last));
 71         a1++;a2++;b1++;b2++;st=n+1;ed=n+2;int sum=2*an+2*bn;
 72         for(int i=1;i<=n;i++)scanf("%s",ss[i]+1);
 73         
 74         for(int i=1;i<=n;i++)
 75             for(int j=1;j<=n;j++)
 76                 if(ss[i][j]=='N')ins(i,j,inf);
 77                 else if(ss[i][j]=='O')ins(i,j,2);
 78         ins(st,a1,2*an);ins(a2,ed,2*an);
 79         ins(st,b1,2*bn);ins(b2,ed,2*bn);
 80         int ans=0;
 81         while(bt_h())ans+=find_flow(st,inf);
 82         if(ans!=sum){printf("No
");continue;}
 83         //反过来 
 84         len=0;memset(last,0,sizeof(last));
 85         for(int i=1;i<=n;i++)
 86             for(int j=1;j<=n;j++)
 87             {
 88                 if(ss[i][j]=='N')ins(i,j,inf);
 89                 else if(ss[i][j]=='O')ins(i,j,2);
 90             }
 91         ins(st,a1,2*an);ins(a2,ed,2*an);
 92         ins(st,b2,2*bn);ins(b1,ed,2*bn);
 93         ans=0;
 94         while(bt_h())ans+=find_flow(st,inf);
 95         
 96         if(ans!=sum){printf("No
");continue;}
 97         else printf("Yes
");
 98     }
 99     return 0;
100 }
原文地址:https://www.cnblogs.com/CHerish_OI/p/8644515.html