zoukankan      html  css  js  c++  java
  • bzoj 2229 [Zjoi2011]最小割(分治+最小割)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=2229

    【题意】

        回答若干个关于割不超过x的点对数目的询问。

    【思路】

        [最小割最多有n-1个,这n-1个最小割构成一个最小割树]

        分治法寻找n-1个最小割。对于当前点集X,任选两点为ST做最小割,然后找出与S相连的所有点和与T相连的所有点构成S集与T集,更新S集与T集的最小割。然后递归处理两个集合。

    【代码】

      1 #include<set>
      2 #include<cmath>
      3 #include<queue>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
     10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     11 using namespace std;
     12 
     13 typedef long long ll;
     14 const int N = 2e3+10;
     15 const int inf = 1e9;
     16 
     17 ll read() {
     18     char c=getchar();
     19     ll f=1,x=0;
     20     while(!isdigit(c)) {
     21         if(c=='-') f=-1; c=getchar();
     22     }
     23     while(isdigit(c))
     24         x=x*10+c-'0',c=getchar();
     25     return x*f;
     26 }
     27 
     28 struct Edge {
     29     int u,v,cap,flow;
     30 };
     31 struct Dinic {
     32     int n,m,s,t;
     33     int d[N],cur[N],vis[N];
     34     vector<int> g[N];
     35     vector<Edge> es;
     36     queue<int> q;
     37     void init(int n) {
     38         this->n=n;
     39         es.clear();
     40         FOR(i,0,n) g[i].clear();
     41     }
     42     void clear() {
     43         FOR(i,0,(int)es.size()-1) es[i].flow=0;
     44     }
     45     void AddEdge(int u,int v,int w) {
     46         es.push_back((Edge){u,v,w,0});
     47         es.push_back((Edge){v,u,0,0});
     48         m=es.size();
     49         g[u].push_back(m-2);
     50         g[v].push_back(m-1);
     51     }
     52     int bfs() {
     53         memset(vis,0,sizeof(vis));
     54         q.push(s); d[s]=0; vis[s]=1;
     55         while(!q.empty()) {
     56             int u=q.front(); q.pop();
     57             FOR(i,0,(int)g[u].size()-1) {
     58                 Edge& e=es[g[u][i]];
     59                 int v=e.v;
     60                 if(!vis[v]&&e.cap>e.flow) {
     61                     vis[v]=1;
     62                     d[v]=d[u]+1;
     63                     q.push(v);
     64                 }
     65             }
     66         }
     67         return vis[t];
     68     }
     69     int dfs(int u,int a) {
     70         if(u==t||!a) return a;
     71         int flow=0,f;
     72         for(int& i=cur[u];i<g[u].size();i++) {
     73             Edge& e=es[g[u][i]];
     74             int v=e.v;
     75             if(d[v]==d[u]+1&&(f=dfs(v,min(a,e.cap-e.flow)))>0) {
     76                 e.flow+=f; 
     77                 es[g[u][i]^1].flow-=f;
     78                 flow+=f; a-=f;
     79                 if(!a) break;
     80             }
     81         }
     82         return flow;
     83     }
     84     int MaxFlow(int s,int t) {
     85         this->s=s,this->t=t;
     86         int flow=0;
     87         while(bfs()) {
     88             memset(cur,0,sizeof(cur));
     89             flow+=dfs(s,inf);
     90         }
     91         return flow;
     92     }
     93 } dc;
     94 
     95 int T,n,m,ans[N][N],b[N],t[N],vis[N],tot;
     96 
     97 void dfs(int u)
     98 {
     99     vis[u]=1;
    100     FOR(i,0,(int)dc.g[u].size()-1) {
    101         Edge& e=dc.es[dc.g[u][i]];
    102         if(!vis[e.v]&&e.cap>e.flow) dfs(e.v);
    103     }
    104 }
    105 void solve(int l,int r)
    106 {
    107     if(l==r) return ;
    108     dc.clear();
    109     int S=b[l],T=b[r],cut;
    110     cut=dc.MaxFlow(S,T);
    111     memset(vis,0,sizeof(vis));
    112     dfs(S);
    113     FOR(i,1,n) if(vis[i])
    114         FOR(j,1,n) if(!vis[j])
    115             ans[i][j]=ans[j][i]=min(ans[i][j],cut);
    116     int L=l,R=r;
    117     FOR(i,l,r) 
    118         if(vis[b[i]]) t[L++]=b[i];
    119         else t[R--]=b[i];
    120     FOR(i,l,r) b[i]=t[i];
    121     solve(l,L-1),solve(L,r);
    122 }
    123 
    124 int main()
    125 {
    126     //freopen("in.in","r",stdin);
    127     //freopen("out.out","w",stdout); 
    128     T=read();
    129     while(T--) {
    130         n=read(),m=read();
    131         dc.init(n+2);
    132         FOR(i,1,m) {
    133             int u=read(),v=read(),w=read();
    134             dc.AddEdge(u,v,w),dc.AddEdge(v,u,w);
    135         }
    136         FOR(i,1,n) {
    137             b[i]=i;
    138             FOR(j,1,n) ans[i][j]=inf;
    139         }
    140         solve(1,n);
    141         int q=read();
    142         while(q--) {
    143             int x=read(),res=0;
    144             FOR(i,1,n) FOR(j,i+1,n)
    145                 if(ans[i][j]<=x) res++;
    146             printf("%d
    ",res);
    147         }
    148         puts("");
    149     }
    150     return 0;
    151 }
  • 相关阅读:
    笨方法学python中执行argv提示ValueError: not enough values to unpack (expected 4, got 1)
    VMware workstation安装
    Redis bigkey分析
    MySQL drop table 影响及过程
    MySQL 大表硬连接删除
    ES elasticsearch 各种查询
    ES elasticsearch 各种聚合
    ES elasticsearch 聚合统计
    ES elasticsearch 实现 count单字段,分组取前多少位,以地理位置中心进行统计
    MySQL行溢出、varchar最多能存多少字符
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5310132.html
Copyright © 2011-2022 走看看