bzoj 1001: [BeiJing2006]狼抓兔子
http://www.lydsy.com/JudgeOnline/problem.php?id=1001
解法1:直接最小割dinic || isap ,据说会卡掉某些人写的丑的dinic
/************************************************************** Problem: 1497 User: 11101001 Language: C++ Result: Accepted Time:576 ms Memory:15356 kb ****************************************************************/ #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn = 600001; const int INF = 0x7fffffff; int n,m,dis[maxn],head[maxn],que[maxn]; struct node{ int v,w,next; }edge[maxn]; int ans,tmp,S,T,num=1; inline void Add_Edge(int u,int v,int w) { edge[++num].v=v;edge[num].w=w;edge[num].next=head[u];head[u]=num; edge[++num].v=u;edge[num].next=head[v];head[v]=num; } bool bfs() { memset(dis,-1,sizeof(dis)); int h=0,t=1; que[h]=dis[0]=0; while(h<t) { int u=que[h++]; if(h==maxn)h=0; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v; if(edge[i].w&&dis[v]<0) { que[t++]=v; dis[v]=dis[u]+1; if(t==maxn)t=0; } } } if(dis[T]==-1)return false; return true; } int dfs(int x,int f) { if(x==T) return f; int mn=0,w; for(int i=head[x];i;i=edge[i].next) { if(edge[i].w&&dis[edge[i].v]==dis[x]+1) { w=f-mn; w=dfs(edge[i].v,min(w,edge[i].w)); edge[i].w-=w; edge[i^1].w+=w; mn+=w; if(mn==f)return f; } } if(!mn)dis[x]=-1; return mn; } void dinic() { while(bfs()) ans+=dfs(S,INF); } int main() { S=0; scanf("%d%d",&n,&m);T=n+m+1; for(int a,i=1;i<=n;i++){ scanf("%d",&a); Add_Edge(S,i,a); } for(int a,b,c,i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); Add_Edge(a,n+i,INF); Add_Edge(b,n+i,INF); Add_Edge(n+i,T,c); tmp+=c; } dinic(); // printf("%d %d\n",tmp,ans); printf("%d\n",tmp-ans); return 0; }
解法2:平面图转对偶图最短路.
/************************************************************** Problem: 1001 User: 11101001 Language: C++ Result: Accepted Time:2900 ms Memory:120432 kb ****************************************************************/ #include<iostream> #include<cstring> #include<cstdio> #define maxn 2000001 using namespace std; int n,m,to; struct data{ int v,next,w; }edge[4*maxn]; int dis[maxn],q[maxn],head[maxn]; bool vis[maxn]; int num; inline void add_edge(int u,int v,int w) { edge[++num].v=v;edge[num].w=w;edge[num].next=head[u];head[u]=num; edge[++num].v=u;edge[num].w=w;edge[num].next=head[v];head[v]=num; } void spfa() { memset(dis,0x3f,sizeof(dis)); int t=0,w=1; dis[0]=q[w]=0;vis[0]=1; while(t!=w) { int u=q[t++]; vis[u]=0; if(t==maxn)t=0; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v; if(dis[v]>dis[u]+edge[i].w) { dis[v]=dis[u]+edge[i].w; if(!vis[v]) { vis[v]=1; q[w++]=v; if(w==maxn)w=0; } } } } } inline void init() { int x; for(int j=1;j<m;j++) { scanf("%d",&x); add_edge(j,to+1,x); } for(int i=1;i<n-1;i++) { for(int j=1;j<m;j++) { scanf("%d",&x); add_edge((i*2)*(m-1)+j,((i*2)-1)*(m-1)+j,x); } } for(int j=1;j<m;j++) { scanf("%d",&x); add_edge(0,((n*2)-3)*(m-1)+j,x); } for(int i=0;i<n-1;i++) { for(int j=1;j<=m;j++) { scanf("%d",&x); if(j==1)add_edge(0,(i*2)*(m-1)+m,x); else if(j==m)add_edge((i*2+1)*(m-1),to+1,x); else add_edge((i*2)*(m-1)+j-1,(i*2)*(m-1)+j+m-1,x); } } for(int i=0;i<n-1;i++) { for(int j=1;j<m;j++) { scanf("%d",&x); add_edge((i*2+1)*(m-1)+j,(i*2)*(m-1)+j,x); } } } int main() { scanf("%d%d",&n,&m); to=(n*m-m-n+1)*2; init(); spfa(); printf("%d\n",dis[to+1]); return 0; }