您的位置:首页 > 理论基础 > 计算机网络

【网络流】hdu3046 Pleasant sheep and big big wolf

2014-09-17 18:13 363 查看
题意:青青大草原上有喜羊羊他们的小羊们还有灰太狼一帮狼,想再要加栅栏使得每只羊和每只狼隔开,求需要的最少的栅栏数量。

难度:2

题解:1连源点,2连汇点,容量无限,各个格子间连边容量为1,求最小割(题解转载自notonlysuccess.com)

hdu3998

题意:(同类问题应该来自《线性规划与网络流》24题)同类问题共三问:(1)最长上升子序列长度(2)每个数用一遍,能够得到的最多长度为s的子序列个数(3)同第二问,a[1]与a
可用多次

难度:5

题解:拆点后做最大流。第一问DP求出s,并得到每个数的f[i]。新增源点s,汇点t,对于节点i,若f[i]=1,则与源点连一条容量为1的弧,若f[i]=s,则与汇点连一条容量为1的弧,每个点与拆点后所得到的点连一条容量为1的弧,入度与原节点连,出度与拆点后的点连,若(j>i) (a[j]>a[i]) (f[j]=f[i]+1),则I j 之间连一条容量为1的弧。第三问将1与s的容量,1与1’的容量,n与n’的容量修改为+oo,若f
=s,则n’与t的容量也为+oo 再算一遍最大流。

#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 205000
#define maxm 2050000
#define inf 2000000000
using namespace std;
int gap[maxn],dis[maxn],pre[maxn],cur[maxn];
int n,NV,m;
struct Edge {
int v,val;
int next;
Edge(){}
Edge( int V , int NEXT , int W = 0 ):v(V),next(NEXT),val(W){}
}edge[maxm];
int maxflow;
int cnt_edge,head[maxn];
void addedge( int u , int v , int flow = 0 ) {
edge[cnt_edge] = Edge(v,head[u],flow);
head[u] = cnt_edge++;
edge[cnt_edge] = Edge(u,head[v]);
head[v] = cnt_edge++;
}
void init() {
cnt_edge = 0;
memset(head,-1,sizeof(int)*(NV+1));
}
int Sap( int st, int en )
{
memset(dis,0,sizeof(int)*( NV+1));
memset(gap,0,sizeof(int)*( NV+1));
for( int i  = 0 ; i <  NV ; i++ )
cur[i] = head[i];
int u = pre[st] = st,maxflow = 0,aug = inf;
gap[0] = NV;
while( dis[st] < NV )
{
loop:    for( int &i = cur[u]; i != -1 ; i = edge[i].next ) {
int v =edge[i].v;
if( edge[i].val && dis[u] == dis[v]+1) {
aug = aug <  edge[i].val? aug: edge[i].val;
pre[v] = u;
u = v;
if( v == en ) {
maxflow += aug;
for( u = pre[u]; v != st ; v = u,u = pre[u] ) {
edge[cur[u]].val -= aug;
edge[cur[u]^1].val += aug;
}
aug = inf;
}
goto loop;
}
}
int mindis =  NV;
for( int i =  head[u]; i != -1 ; i =  edge[i].next ) {
int v =  edge[i].v;
if(  edge[i].val && mindis > dis[v] ) {
cur[u] = i;
mindis = dis[v];
}
}
if( --gap[dis[u]] == 0 ) break;
gap[ dis[u] = mindis+1 ]++;
u = pre[u];
}
return maxflow;
}
int N,M;
int main() {
int cas = 1;
while(~scanf("%d%d",&N,&M)) {
printf("Case %d:\n",cas++);
int st = N*M , en = st + 1;
NV = en + 1;
init();
for(int i=0;i<N;i++)
for(int j=0;j<M;j++) {
int ff;
scanf("%d",&ff);
if(ff == 1) addedge(st,i*M+j,inf);
if(ff == 2) addedge(i*M+j,en,inf);
if(i<N-1) addedge(i*M+j,i*M+j+M,1);
if(i>0) addedge(i*M+j,i*M+j-M,1);
if(j<M-1) addedge(i*M+j,i*M+j+1,1);
if(j > 0) addedge(i*M+j,i*M+j-1,1);
}
int ans = Sap(st,en);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: