[ZJOI2011]最小割

题解:

以前看过,思维挺神奇的一道题目

首先可以证明最小割是不能相交的

那么我们就可以找到任意两点求一次最小割然后将割的两边分开来再递归这个过程

另外最小割就是vis=0与vis=1之间的连边

分治的时候把一个局部变量写了全局变量还有83??? 找个好久。。

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxn 3000
#define INF 1e9
int dis[200][200],l,n,m,s,t;
struct {
    int a,b,c,flow;
}a[maxn*2],tmp[maxn*2];
bool fz1[200],vis[200];
int d[200],head[200];
void arr(int x,int y,int z)
{
    a[++l].a=head[x];
    a[l].b=y;
    a[l].c=z;
    a[l].flow=0;
    head[x]=l;
}
queue<int> q;
bool bfs(){
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(s);
    d[s]=0; vis[s]=1;
    while (!q.empty())
    {
        int x=q.front();q.pop();
        int u=head[x];
        while (u)
        {
            int v=a[u].b;
            if (!vis[v]&&a[u].c>a[u].flow)
            {
                vis[v]=1;
                d[v]=d[x]+1;
                q.push(v);
            }
            u=a[u].a;
        }
    }
    return(vis[t]);
}
int dfs(int x,int y)
{
    if (x==t||y==0) return y;
    int flow=0,f,tmp;
    int u=head[x];
    while (u)
    {
        int v=a[u].b;
        if (d[x]+1==d[v]&&(f=dfs(v,min(y,a[u].c-a[u].flow)))>0)
        {
            a[u].flow+=f;
            if (u%2) tmp=u+1; else tmp=u-1;
            a[tmp].flow-=f;
            flow+=f; 
            y-=f;
            if (y==0) break;
        }
        u=a[u].a;
    }
    return(flow);
}
int maxflow()
{
    int flow=0;
    while (bfs())
    {
        flow+=dfs(s,INF);
    }
    return(flow);
}
void get_ans(int ss,int tt)
{
    for (int i=1;i<=l;i++) a[i].flow=0;
    bool tmp3[200],fz2[200];
    s=ss; t=tt;
    int ans=maxflow();
    memcpy(tmp3,vis,sizeof(vis));
    for (int i=1;i<=n;i++)
      if (vis[i])
        for (int j=1;j<=n;j++)
          if (!vis[j])
            dis[i][j]=min(dis[i][j],ans),dis[j][i]=min(ans,dis[j][i]);
    int tmp1=0,tmp2=0,num=0;
    for (int i=1;i<=n;i++)
      if (vis[i]&&fz1[i])
      {
          num++;
          if (!tmp1) tmp1=i; else tmp2=i;
      }
    memcpy(fz2,fz1,sizeof(fz1));
    for (int i=1;i<=n;i++)
      if (!vis[i]) fz1[i]=0;
    if (num>=2)
    {
    /*    l=0; memset(head,0,sizeof(head));
        for (int i=1;i<=m;i++)
          if (vis[tmp[i].a]&&vis[tmp[i].b]&&
              fz1[tmp[i].a]&&fz1[tmp[i].b])
          {
               arr(tmp[i].a,tmp[i].b,tmp[i].c);
               arr(tmp[i].b,tmp[i].a,tmp[i].c);
          } */
         get_ans(tmp1,tmp2);
    }
    memcpy(vis,tmp3,sizeof(tmp3));
    memcpy(fz1,fz2,sizeof(fz2));
    tmp1=0,tmp2=0,num=0;
    for (int i=1;i<=n;i++)
      if (!vis[i]&&fz1[i])
      {
          num++;
          if (!tmp1) tmp1=i; else tmp2=i;
      }
    for (int i=1;i<=n;i++)
      if (vis[i]) fz1[i]=0;
    if (num>=2)
    {
    /*    l=0; memset(head,0,sizeof(head));
        for (int i=1;i<=m;i++)
          if (!vis[tmp[i].a]&&!vis[tmp[i].b]
          &&  fz1[tmp[i].a]&&fz1[tmp[i].b])
          {
               arr(tmp[i].a,tmp[i].b,tmp[i].c);
               arr(tmp[i].b,tmp[i].a,tmp[i].c);
          } */
        get_ans(tmp1,tmp2);
    }   
    memcpy(fz1,fz2,sizeof(fz2));
}
int main()
{
    std::ios::sync_with_stdio(false);
    int T;
    cin>>T;
    for (int p=1;p<=T;p++)
    {
        
        l=0; memset(head,0,sizeof(head));
        memset(fz1,1,sizeof(fz1));
    cin>>n>>m;
    for (int i=1;i<=n;i++)
      for (int j=1;j<=n;j++) dis[i][j]=INF;
    for (int i=1;i<=m;i++)
    {
        int c,d,e;
        cin>>c>>d>>e;
        tmp[i].a=c; tmp[i].b=d; tmp[i].c=e;
        arr(c,d,e); arr(d,c,e);
    }
    get_ans(1,n);
    int q;
    cin>>q;
    int x;
    for (int i=1;i<=q;i++)
    {
        cin>>x;
        int ans=0;
        for (int j1=1;j1<=n;j1++)
          for (int j2=j1+1;j2<=n;j2++)
            if (dis[j1][j2]<=x||dis[j1][j2]==INF) ans++;
        cout<<ans<<endl;
    }
    cout<<endl;

    }
    return 0;
}

 

posted @ 2018-03-12 15:01  尹吴潇  阅读(144)  评论(0编辑  收藏  举报