boat的sap最大流模板,抄袭…袭…
#include<cstdio>
#include<fstream>
#include<cstring>
using namespace std;
const int MAXV = 2000;
const int MAXE=100000;
const int inf = 21000000;
struct Edge
{
int v,next,w;
}edge[MAXE],e[MAXE];
int cnt,n,m,s,t,V,maxflow;
int head[MAXV];
void addedge(int u,int v,int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].v=u;
edge[cnt].w=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}int getNum()
{
char c;
int num = 0;
while(c=getchar())
if(c<='9'&&c>='0')break;
while(c<='9'&&c>='0'){
num=num*10+c-'0';
c = getchar();
}
return num;
}
int sap()
{
int pre[MAXV],cur[MAXV],dis[MAXV],gap[MAXV];
int flow=0,aug=inf,u;
bool flag;
for(int i=0;i<V;i++){
cur[i]=head[i];
gap[i]=dis[i]=0;
}
gap[s]=V;
u=pre[s]=s;
while(dis[s]<V){
flag=0;
for(int &j=cur[u];j!=-1;j=e[j].next){
int v=e[j].v;
if(e[j].w>0&&dis[u]==dis[v]+1){
flag=1;
if(e[j].w<aug) aug=e[j].w;
pre[v]=u;
u=v;
if(u==t){
flow+=aug;
while(u!=s){
u=pre[u];
e[cur[u]].w-=aug;
e[cur[u]^1].w+=aug;
}
aug=inf;
}
break;
}
}
if(flag)
continue;
int mindis=V;
for(int j=head[u];j!=-1;j=e[j].next){
int v=e[j].v;
if(e[j].w>0&&dis[v]<mindis){
mindis=dis[v];
cur[u]=j;
}
}
if((--gap[dis[u]])==0)
break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return flow;
}
int main()
{
int f;
scanf("%d",&f);
while(f--)
{
int S,H;
scanf("%d%d%d%d",&n,&m,&S,&H);
memset(head,-1,sizeof(head));
s=S+n;t=H;
cnt=0;
for(int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
addedge(i,i+n,a);
addedge(i+n,i,a);
}
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
addedge(a+n,b,inf);
addedge(b+n,a,inf);
}
printf("%d\n",sap());
}
}
POJ 1966 Cable TV Network
题意:无向图的点联通度:求至少去掉几个点后剩下的图不连通。
(1)一个具有 N 个顶点的图,在去掉任意 k-1 个顶点后(1<=K<=N) 所得的子图仍连通,而去掉 K 个顶点后的图不连通则称 G 是连通的, K 称作图 G 的点连通度,记作 K(G)
(2)相应地如果至少去掉 K 条边使这个图不连通,则 K 成为图的边连通度
相关概念:
边连通度:
为每条边赋权值为1,然后求确定一点作为源点,枚举此点外的每个点作为汇点求最大流。
也可以用stoer_wagner算法求得无向图的最小割
点连通度:
求一个给定的无向图的点连通度,可以转换为求边连通度,怎么转换就如下所示:
将点连通度转化为边连通度时怎么建图呢:
1 .构造一个网络 N
若 G 为无向图:
若 G 为有向图:
转自:http://blog.sina.com.cn/s/blog_64675f540100l6u3.html
Dinic 邻接表,顺便模板ORZ~
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define Max 0x1fffffff
#define size 200
struct edge{int from, to, val, next;}e[140000];
int v[size], que[size], dis[size], cnt, cur[size], ee[20000][2];
void insert(int from, int to, int va)
{
e[cnt].from = from, e[cnt].to = to; e[cnt].val = va;
e[cnt].next = v[from];v[from] = cnt++;
e[cnt].from = to, e[cnt].to = from; e[cnt].val = 0;
e[cnt].next = v[to];v[to] = cnt++;
}
bool bfs(int n, int s, int t)
{
int head, tail, id;
head = tail = 0; que[tail++] = s;
memset(dis, -1, sizeof(int) * n);dis[s] = 0;
while(head < tail) // bfs,得到顶点i的距s的最短距离dis[i]
for(id = v[que[head++]]; id != -1; id = e[id].next)
if (e[id].val > 0 && dis[e[id].to] == -1)
{
dis[e[id].to] = dis[e[id].from] + 1;
que[tail++] = e[id].to;
if (e[id].to == t) return true;
}
return false;
}
int Dinic(int n, int s, int t)
{
int maxflow = 0, tmp, i;
while(bfs(n, s, t))
{
int u = s, tail = 0;
for(i = 0; i < n; i++) cur[i] = v[i];
while(cur[s] != -1)
if (u != t && cur[u] != -1 && e[cur[u]].val > 0 && dis[u] != -1 && dis[u] + 1 == dis[e[cur[u]].to])
{que[tail++] = cur[u]; u = e[cur[u]].to;}
else if (u == t)
{
for(tmp = Max, i = tail - 1; i >= 0; i--) tmp = min(tmp, e[que[i]].val);
for(maxflow += tmp, i = tail - 1; i >= 0; i--)
{
e[que[i]].val -= tmp;
e[que[i] ^ 1].val += tmp;
if (e[que[i]].val == 0) tail = i;
}
u = e[que[tail]].from;
}
else
{
while(tail > 0 && u != s && cur[u] == -1) u = e[que[--tail]].from;
cur[u] = e[cur[u]].next;
}
}
return maxflow;
}
int n ,m;
int main()
{
while(scanf("%d%d", &n, &m) != EOF)
{
for(int i = 0; i < m; i++)
{
while(getchar() != '(');
scanf("%d,%d)", &ee[i][0], &ee[i][1]);
}
int s = n, ans = Max;
for(int t = 1; t < n; t++)
{
memset(v, -1, sizeof(int) * (n + n)); cnt = 0;
for(int i = 0; i < n; i++) insert(i, i + n, 1);
for(int i = 0; i < m; i++)
insert(ee[i][0] + n, ee[i][1], Max), insert(ee[i][1] + n, ee[i][0], Max);
ans = min(ans, Dinic(n + n, s, t));
}
if (ans >= Max) ans = n;
printf("%d\n", ans);
}
return 0;
}