标签:bottom memory main gaussian roman comment sam each const
和HDOJ4888是一样的问题,最大流推断多解
1.把ISAP卡的根本出不来结果,仅仅能把全为0或者全为满流的给特判掉......
2.在残量网络中找大于2的圈要用一种类似tarjian的方法从汇点開始找,推断哪些点没有到汇点
3 1 1 5 5 2 2 0 10 0 10 2 2 2 2 2 2
Case #1: So simple! Case #2: So naive! Case #3: So young!
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int maxn=20000; const int maxm=500000; const int INF=0x3f3f3f3f; struct Edge { int to,next,cap,flow; }edge[maxm]; int Size,Adj[maxn]; int gap[maxn],dep[maxn],pre[maxn],cur[maxn]; void init() { Size=0; memset(Adj,-1,sizeof(Adj)); } void addedge(int u,int v,int w,int rw=0) { edge[Size].to=v; edge[Size].cap=w; edge[Size].next=Adj[u]; edge[Size].flow=0; Adj[u]=Size++; edge[Size].to=u; edge[Size].cap=rw; edge[Size].next=Adj[v]; edge[Size].flow=0; Adj[v]=Size++; } int sap(int start,int end,int N) { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,Adj,sizeof(Adj)); int u=start; pre[u]=-1; gap[0]=N; int ans=0; while(dep[start]<N) { if(u==end) { int Min=INF; for(int i=pre[u];~i;i=pre[edge[i^1].to]) if(Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for(int i=pre[u];~i;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; } u=start; ans+=Min; continue; } bool flag=false; int v; for(int i=cur[u];~i;i=edge[i].next) { v=edge[i].to; if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if(flag) { u=v; continue; } int Min=N; for(int i=Adj[u];~i;i=edge[i].next) if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min) { Min=dep[edge[i].to]; cur[u]=i; } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if(u!=start) u=edge[pre[u]^1].to; } return ans; } int n,m; int a[maxn],b[maxn]; bool vis[maxn],no[maxn]; int Stack[maxm],stk; bool dfs(int u,int pre,bool flag) { vis[u]=true; Stack[stk++]=u; for(int i=Adj[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==pre) continue; if(edge[i].flow>=edge[i].cap) continue; if(!vis[v]) { if(dfs(v,u,edge[i^1].cap>edge[i^1].flow)) return true; } else if(!no[v]) return true; } if(flag==false) { while(true) { int v=Stack[--stk]; no[v]=true; if(v==u) break; } } return false; } int main() { int T_T,cas=1; scanf("%d",&T_T); while(T_T--) { scanf("%d%d",&n,&m); int sum1=0,sum2=0; for(int i=1;i<=n;i++) { scanf("%d",a+i); sum1+=a[i]; } for(int i=1;i<=m;i++) { scanf("%d",b+i); sum2+=b[i]; } if(sum1!=sum2) { printf("Case #%d: So naive!\n",cas++); continue; } if(sum1==sum2&&((sum1==0)||(sum1==n*m*9))) { printf("Case #%d: So simple!\n",cas++); continue; } /*************build graph*****************/ init(); for(int i=1;i<=n;i++) addedge(0,i,a[i]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) addedge(i,n+j,9); for(int i=1;i<=m;i++) addedge(i+n,n+m+1,b[i]); /*************build graph*****************/ int MaxFlow=sap(0,n+m+1,n+m+2); if(MaxFlow!=sum1) { printf("Case #%d: So naive!\n",cas++); continue; } stk=0; memset(vis,0,sizeof(vis)); memset(no,0,sizeof(no)); if(dfs(n+m+1,n+m+1,0)) { printf("Case #%d: So young!\n",cas++); } else { printf("Case #%d: So simple!\n",cas++); } } return 0; }
HDOJ 4975 A simple Gaussian elimination problem.
标签:bottom memory main gaussian roman comment sam each const
原文地址:http://www.cnblogs.com/jzssuanfa/p/6931737.html