BZOJ2229: [Zjoi2011]最小割

题解:

真是一道神题!!!

大家还是围观JZP的题解吧(网址找不到了。。。)

代码:

  1 #include<cstdio>
  2   
  3 #include<cstdlib>
  4   
  5 #include<cmath>
  6   
  7 #include<cstring>
  8   
  9 #include<algorithm>
 10   
 11 #include<iostream>
 12   
 13 #include<vector>
 14   
 15 #include<map>
 16   
 17 #include<set>
 18   
 19 #include<queue>
 20   
 21 #include<string>
 22   
 23 #define inf 1000000000
 24   
 25 #define maxn 200000+5
 26   
 27 #define maxm 200000+5
 28   
 29 #define eps 1e-10
 30   
 31 #define ll long long
 32   
 33 #define pa pair<int,int>
 34   
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36   
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38   
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40   
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42   
 43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 44   
 45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
 46   
 47 #define mod 1000000007
 48   
 49 using namespace std;
 50   
 51 inline int read()
 52   
 53 {
 54   
 55     int x=0,f=1;char ch=getchar();
 56   
 57     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 58   
 59     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 60   
 61     return x*f;
 62   
 63 }
 64 int  n,m,s,t,cut[200][200],a[maxm],b[maxm],c[maxm],maxflow,tot=1,head[maxn],cur[maxn],h[maxn];
 65   
 66 queue<int>q;
 67 bool v[maxn];
 68   
 69 struct edge{int go,next,v;}e[maxm];
 70   
 71 inline void add(int x,int y,int v)
 72   
 73 {
 74   
 75     e[++tot]=(edge){y,head[x],v};head[x]=tot;
 76   
 77     e[++tot]=(edge){x,head[y],0};head[y]=tot;
 78   
 79 }
 80   
 81 bool bfs()
 82   
 83 {
 84   
 85     for(int i=1;i<=n;i++)h[i]=-1;
 86   
 87     q.push(s);h[s]=0;
 88   
 89     while(!q.empty())
 90   
 91     {
 92   
 93         int x=q.front();q.pop();
 94   
 95         for(int i=head[x];i;i=e[i].next)
 96   
 97          if(e[i].v&&h[e[i].go]==-1)
 98   
 99          {
100   
101             h[e[i].go]=h[x]+1;q.push(e[i].go);
102   
103          }
104   
105     }
106   
107     return h[t]!=-1;
108   
109 }
110   
111 int dfs(int x,int f)
112   
113 {
114   
115     if(x==t) return f;
116   
117     int tmp,used=0;
118   
119     for(int i=cur[x];i;i=e[i].next)
120   
121      if(e[i].v&&h[e[i].go]==h[x]+1)
122   
123     {
124   
125         tmp=dfs(e[i].go,min(e[i].v,f-used));
126   
127         e[i].v-=tmp;if(e[i].v)cur[x]=i;
128   
129         e[i^1].v+=tmp;used+=tmp;
130   
131         if(used==f)return f;      
132   
133     }
134   
135     if(!used) h[x]=-1;
136   
137     return used;
138   
139 }
140 inline void dfs(int x)
141 {
142     v[x]=1;
143     for4(i,x)if(e[i].v&&!v[y])dfs(y);
144 }
145   
146 void dinic()
147   
148 {
149     maxflow=0;
150   
151     while(bfs())
152   
153     {
154   
155         for (int i=1;i<=n;i++)cur[i]=head[i];maxflow+=dfs(s,inf);
156   
157     }
158   
159 }
160 inline void solve(int l,int r)
161 {
162     if(l==r)return;
163     s=b[l];t=b[r];
164     for1(i,tot)e[i].v=a[i];
165     dinic();
166     for1(i,n)v[i]=0;
167     dfs(s);
168     for1(i,n)if(v[i])for1(j,n)if(!v[j])cut[i][j]=cut[j][i]=min(cut[i][j],maxflow);
169     int t1=l-1,t2=r+1;
170     for2(i,l,r)if(v[b[i]])c[++t1]=b[i];else c[--t2]=b[i];
171     for2(i,l,r)b[i]=c[i];
172     solve(l,t1);solve(t2,r);
173 }
174   
175 int main()
176   
177 {
178     int T=read();
179     while(T--)
180     {
181         n=read();m=read();
182         for1(i,n)head[i]=0;tot=1;
183         for1(i,m)
184         {
185             int x=read(),y=read(),w=read();
186             add(x,y,w);add(y,x,w);
187         }
188         for1(i,tot)a[i]=e[i].v;
189         for1(i,n)b[i]=i;
190         for1(i,n)for1(j,n)cut[i][j]=inf;
191         solve(1,n);
192         int q=read();
193         while(q--)
194         {
195             int x=read(),ans=0;
196             for1(i,n)for2(j,i+1,n)if(cut[i][j]<=x)ans++;
197             printf("%d\n",ans);
198         }
199         printf("\n");
200     }
201   
202     return 0;
203   
204 }  
View Code

2229: [Zjoi2011]最小割

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 685  Solved: 263
[Submit][Status]

Description

小 白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割。 对于带权图来说,将所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而s,t的最小割指的是在关于s,t的割中容量最小的割” 现给定一张无向图,小白有若干个形如“图中有多少对点它们的最小割的容量不超过x呢”的疑问,小蓝虽然很想回答这些问题,但小蓝最近忙着挖木块,于是作为 仍然是小蓝的好友,你又有任务了。

Input

输入文件第一行有 且只有一个正整数T,表示测试数据的组数。 对于每组测试数据, 第一行包含两个整数n,m,表示图的点数和边数。 下面m行,每行3个正整数u,v,c(1<=u,v<=n,0<=c<=106),表示有一条权为c的无向边(u,v) 接下来一行,包含一个整数q,表示询问的个数 下面q行,每行一个整数x,其含义同题目描述。

Output

对于每组测试数据,输出应包括q行,第i行表示第i个问题的答案。对于点对(p,q)和(q,p),只统计一次(见样例)。

两组测试数据之间用空行隔开。

Sample Input

1
5 0
1
0

Sample Output

10

【数据范围】
对于100%的数据 T<=10,n<=150,m<=3000,q<=30,x在32位有符号整数类型范围内。
图中两个点之间可能有多条边

HINT

Source

posted @ 2014-12-30 18:32  ZYF-ZYF  Views(308)  Comments(0Edit  收藏  举报