一看:裸二分图最大匹配/最大流么,码码码
交,WA..
仔细读题,是这样的,一旦有一个题答不出游戏就结束了,看起来需要动态加边的最大流?
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #define Ri(x) ((x)+m) using namespace std; inline int rd() { int ret=0,f=1; char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=2048; const int INF=1<<29; struct Edge { int next,to,w; } e[MAXN<<2]; int ecnt=1,head[MAXN]; inline void add(int x,int y,int w) { e[++ecnt].next = head[x]; e[ecnt].to = y; e[ecnt].w = w; head[x] = ecnt; } int n,m; int S,T; bool visr[MAXN]; int dep[MAXN]; queue<int> Q; bool bfs() { memset(dep,0,sizeof(dep)); Q.push(S); dep[S]=1; while(!Q.empty()) { int top=Q.front(); Q.pop(); for(int i=head[top]; i; i=e[i].next) { int v=e[i].to; if(!e[i].w||dep[v]) continue; dep[v]=dep[top]+1; Q.push(v); } } return dep[T]; } int cur[MAXN]; int dfs(int x,int flow) { if(x==T) return flow; int used=0,tmp; for(int i=cur[x]; i; i=e[i].next) { int v=e[i].to; if(dep[v]!=dep[x]+1) continue; tmp=dfs(v,min(e[i].w,flow-used)); e[i].w-=tmp; e[i^1].w+=tmp; used+=tmp; if(e[i].w) cur[x]=i; if(used==flow) return flow; } if(!used) dep[x]=0; return used; } int mxflow; void dinic() { while(bfs()) { memcpy(cur,head,sizeof(head)); mxflow+=dfs(S,INF); } } bool vis[MAXN]; int main() { n=rd(); m=rd(); S=n+m+1; T=n+m+2; int x,y; for(int i=1; i<=m; i++) { add(S,i,1),add(i,S,0); x=rd();y=rd();x++;y++; add(i,Ri(x),1);add(Ri(x),i,0); if(!vis[x]) add(Ri(x),T,1),add(T,Ri(x),0); vis[x]=1; if(x!=y) { add(i,Ri(y),1);add(Ri(y),i,0); if(!vis[y]) add(Ri(y),T,1),add(T,Ri(y),0); vis[y]=1; } dinic(); if(mxflow<i) return cout<<mxflow,0; } cout<<mxflow; return 0; }
但是有这样一个事情,如果能答x道,一定能答y (y<x)道(显然啊)
因此可以二分一下!dinic的优秀复杂度,不慢的
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #define Ri(x) ((x)+m) using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=2048; const int INF=1<<29; struct Edge{ int next,to,w; }e[MAXN<<2]; int ecnt=1,head[MAXN]; inline void add(int x,int y,int w){ e[++ecnt].next = head[x]; e[ecnt].to = y; e[ecnt].w = w; head[x] = ecnt; } int n,m; int S,T; int dep[MAXN]; queue<int> Q; bool bfs(){ memset(dep,0,sizeof(dep)); Q.push(S);dep[S]=1; while(!Q.empty()){ int top=Q.front();Q.pop(); for(int i=head[top];i;i=e[i].next){ int v=e[i].to; if(!e[i].w||dep[v]) continue; dep[v]=dep[top]+1; Q.push(v); } } return dep[T]; } int cur[MAXN]; int dfs(int x,int flow){ if(x==T) return flow; int used=0,tmp; for(int i=cur[x];i;i=e[i].next){ int v=e[i].to; if(dep[v]!=dep[x]+1) continue; tmp=dfs(v,min(e[i].w,flow-used)); e[i].w-=tmp;e[i^1].w+=tmp; used+=tmp; if(e[i].w) cur[x]=i; if(used==flow) return flow; } if(!used) dep[x]=0; return used; } int mxflow; void dinic(){ while(bfs()){ memcpy(cur,head,sizeof(head)); mxflow+=dfs(S,INF); } } int savx[MAXN],savy[MAXN]; bool solve(int mid){ ecnt=1; memset(head,0,sizeof(head)); mxflow=0; int x,y; for(int i=1;i<=mid;i++){ x=savx[i];y=savy[i]; add(i,Ri(x),1);add(Ri(x),i,0); if(x==y) continue; add(i,Ri(y),1),add(Ri(y),i,0); } for(int i=1;i<=m;i++) add(S,i,1),add(i,S,0); for(int i=1;i<=n;i++){ add(Ri(i),T,1);add(T,Ri(i),0); } dinic(); return mxflow==mid; } int main(){ n=rd();m=rd(); S=n+m+1;T=n+m+2; int x,y; for(int i=1;i<=m;i++){ savx[i]=rd()+1;savy[i]=rd()+1; add(i,Ri(x),1);add(Ri(x),i,0); } int l=0,r=m,mid,ans; while(l<=r){ mid=(l+r)>>1; if(solve(mid)) l=mid+1,ans=mid; else r=mid-1; } cout<<ans; return 0; }