bzoj4519: [Cqoi2016]不同的最小割(分治最小割)

Posted CHerish_OI

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4519: [Cqoi2016]不同的最小割(分治最小割)相关的知识,希望对你有一定的参考价值。

4519: [Cqoi2016]不同的最小割

题目:传送门 

题解:

   同BZOJ 2229

   基本一样的题目啊,就最后用set记录一下就ok

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<set>
  7 using namespace std;
  8 const int inf=999999999;
  9 struct node
 10 {
 11     int x,y,c,next,other;
 12 }a[210000];int len,last[110000];
 13 int st,ed,n,m,T,ans;
 14 void ins(int x,int y,int c)
 15 {
 16     int k1,k2;
 17     k1=++len;
 18     a[len].x=x;a[len].y=y;a[len].c=c;
 19     a[len].next=last[x];last[x]=len;
 20     
 21     k2=++len;
 22     a[len].x=y;a[len].y=x;a[len].c=c;
 23     a[len].next=last[y];last[y]=len;
 24     
 25     a[k1].other=k2;
 26     a[k2].other=k1;
 27 }
 28 int list[110000],h[110000],head,tail;
 29 bool bt_h()
 30 {
 31     memset(h,0,sizeof(h));h[st]=1;
 32     list[1]=st;head=1;tail=2;
 33     while(head!=tail)
 34     {
 35         int x=list[head];
 36         for(int k=last[x];k;k=a[k].next)
 37         {
 38             int y=a[k].y;
 39             if(h[y]==0 && a[k].c)
 40             {
 41                 h[y]=h[x]+1;
 42                 list[tail++]=y;
 43             }
 44         }
 45         head++;
 46     }
 47     if(h[ed])return true;
 48     return false;
 49 }
 50 int find_flow(int x,int flow)
 51 {
 52     if(x==ed)return flow;
 53     int s=0,t;
 54     for(int k=last[x];k;k=a[k].next)
 55     {
 56         int y=a[k].y;
 57         if(h[y]==h[x]+1 && a[k].c && s<flow)
 58         {
 59             s+=t=find_flow(y,min(a[k].c,flow-s));
 60             a[k].c-=t;a[a[k].other].c+=t;
 61         }
 62     }
 63     if(s==0)h[x]=0;
 64     return s;
 65 }
 66 int d[110000],num[110000],sta[110000],anss[1100][1100];
 67 void re_num(int x)
 68 {
 69     num[x]=1;
 70     for(int k=last[x];k;k=a[k].next)
 71     {
 72         int y=a[k].y;
 73         if(a[k].c && !num[y])
 74             re_num(y);
 75     }
 76 }
 77 void solve(int l,int r)
 78 {
 79     if(l==r)return ;
 80     for(int i=1;i<=len;i+=2)a[i].c=a[i+1].c=(a[i].c+a[i+1].c)>>1;
 81     st=d[l];ed=d[r];ans=0;
 82     while(bt_h())ans+=find_flow(st,inf);
 83     memset(num,0,sizeof(num));
 84     re_num(st);
 85     for(int i=1;i<=n;i++)
 86         if(num[i])
 87             for(int j=1;j<=n;j++)
 88                 if(!num[j])
 89                     anss[i][j]=anss[j][i]=min(anss[i][j],ans);
 90     int L=l,R=r;
 91     for(int i=l;i<=r;i++)
 92     {
 93         if(num[d[i]])sta[L++]=d[i];
 94         else      sta[R--]=d[i];
 95     }
 96     for(int i=l;i<=r;i++)d[i]=sta[i];
 97     solve(l,L-1);solve(R+1,r);
 98 }
 99 set<int> q;
100 set<int> :: iterator it;
101 int main()
102 {
103     scanf("%d%d",&n,&m);
104     len=0;memset(last,0,sizeof(last));int x,y,c;
105     for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&c),ins(x,y,c);
106     for(int i=1;i<=n;i++)d[i]=i;memset(anss,63,sizeof(anss));
107     solve(1,n);
108     for(int i=1;i<=n;i++)
109         for(int j=i+1;j<=n;j++)
110             q.insert(anss[i][j]);
111     printf("%d\\n",q.size());
112     return 0;
113 }

 

以上是关于bzoj4519: [Cqoi2016]不同的最小割(分治最小割)的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ4519][CQOI2016]不同的最小割

最小割分治(最小割树):BZOJ2229 && BZOJ4519

「CQOI2016」不同的最小割

最小割树 - CQOI2016不同的最小割

P4123 [CQOI2016]不同的最小割

bzoj4823: [Cqoi2017]老C的方块(最小割)