bzoj2229: [Zjoi2011]最小割(最小割树)

传送门

这题是用最小割树做的(不明白最小割树是什么的可以去看看这一题->这里

有了最小割树就很简单了……点数那么少……每次跑出一个最大流就暴力搞一遍就好了

  1 //minamoto
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<queue>
  7 #define inf 0x3f3f3f3f
  8 using namespace std;
  9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 10 char buf[1<<21],*p1=buf,*p2=buf;
 11 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
 12 inline int read(){
 13     #define num ch-'0'
 14     char ch;bool flag=0;int res;
 15     while(!isdigit(ch=getc()))
 16     (ch=='-')&&(flag=true);
 17     for(res=num;isdigit(ch=getc());res=res*10+num);
 18     (flag)&&(res=-res);
 19     #undef num
 20     return res;
 21 }
 22 char sr[1<<21],z[20];int C=-1,Z;
 23 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
 24 inline void print(int x){
 25     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
 26     while(z[++Z]=x%10+48,x/=10);
 27     while(sr[++C]=z[Z],--Z);sr[++C]='
';
 28 }
 29 const int N=205,M=10005;
 30 int head[N],Next[M],ver[M],edge[M],ee[M],tot=1;
 31 queue<int> q;
 32 inline void add(int u,int v,int e){
 33     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,ee[tot]=e;
 34     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=e,ee[tot]=e;
 35 }
 36 int cur[N],dep[N],n,m,S,T;
 37 bool bfs(){
 38     memset(dep,-1,sizeof(dep));
 39     for(int i=1;i<=n;++i) cur[i]=head[i];
 40     while(!q.empty()) q.pop();
 41     q.push(S),dep[S]=0;
 42     while(!q.empty()){
 43         int u=q.front();q.pop();
 44         for(int i=head[u];i;i=Next[i])
 45         if(dep[ver[i]]<0&&edge[i]){
 46             q.push(ver[i]),dep[ver[i]]=dep[u]+1;
 47             if(ver[i]==T) return true;
 48         }
 49     }
 50     return false;
 51 }
 52 int dfs(int u,int limit){
 53     if(u==T||!limit) return limit;
 54     int flow=0,f;
 55     for(int i=cur[u];i;cur[u]=i=Next[i]){
 56         int v=ver[i];
 57         if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){
 58             flow+=f,limit-=f;
 59             edge[i]-=f,edge[i^1]+=f;
 60             if(!limit) break;
 61         }
 62     }
 63     if(!flow) dep[u]=-1;
 64     return flow;
 65 }
 66 int dinic(){
 67     int flow=0;
 68     while(bfs()) flow+=dfs(S,inf);
 69     return flow;
 70 }
 71 int id[N],tmp[N],ans[N][N];
 72 void solve(int L,int R){
 73     if(L==R) return;
 74     for(int i=2;i<=tot;i+=2) edge[i]=edge[i^1]=ee[i];
 75     S=id[L],T=id[R];
 76     int flow=dinic();
 77     for(int i=1;i<=n;++i)
 78     if(~dep[i])
 79     for(int j=1;j<=n;++j)
 80     if(dep[j]<0)
 81     cmin(ans[i][j],flow),cmin(ans[j][i],flow);
 82     int l=L,r=R;
 83     for(int i=L;i<=R;++i)
 84     if(~dep[id[i]]) tmp[l++]=id[i];
 85     else tmp[r--]=id[i];
 86     memcpy(id+L,tmp+L,sizeof(int)*(R-L+1));
 87     solve(L,l-1),solve(r+1,R);
 88 }
 89 inline void init(){
 90     memset(head,0,sizeof(head)),tot=1,memset(ans,0x3f,sizeof(ans));
 91 }
 92 int main(){
 93     //freopen("testdata.in","r",stdin);
 94     int T=read();
 95     while(T--){
 96         init();
 97         n=read(),m=read();
 98         for(int i=1;i<=m;++i){
 99             int u=read(),v=read(),e=read();add(u,v,e);
100         }
101         for(int i=1;i<=n;++i) id[i]=i;
102         solve(1,n);
103         int q=read();
104         while(q--){
105             int k=read(),res=0;
106             for(int i=1;i<=n;++i)
107             for(int j=i+1;j<=n;++j)
108             if(ans[i][j]<=k) ++res;
109             print(res);
110         }
111         sr[++C]='
';
112     }
113     Ot();
114     return 0;
115 }
原文地址:https://www.cnblogs.com/bztMinamoto/p/9571271.html