题意:有n个锦囊妙计,m道题。先从第1道题做起,每道题都有两个妙计可以解决,解决之后才能进入下一题,每个妙计只能用一次,求最多能解决多少题
题解:二分答案+网络流check
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #define S 0 #define T 2001 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } queue<int> qu; int cnt=1,n,m; int head[2005],q[2005]; struct edge{ int to,next,w; }e[50005]; void ins(int f,int t,int w){e[++cnt].next=head[f];head[f]=cnt;e[cnt].to=t;e[cnt].w=w;} void insw(int f,int t,int w){ins(f,t,w);ins(t,f,0);} int dfs(int x,int f) { if(x==T)return f; int used=0; for(int i=head[x];i;i=e[i].next) if(e[i].w&&q[e[i].to]==q[x]+1) { int w=dfs(e[i].to,min(e[i].w,f-used)); used+=w;e[i].w-=w;e[i^1].w+=w; if(f==used)return f; } return used; } bool bfs(int lim) { memset(q,0,sizeof(q));q[S]=1;qu.push(S); while(!qu.empty()) { int x=qu.front();qu.pop(); for(int i=head[x];i;i=e[i].next) if(e[i].w&&!q[e[i].to]&&(e[i].to-n<=lim||e[i].to==T)) {q[e[i].to]=q[x]+1;qu.push(e[i].to);} } return q[T]>0; } bool check(int x) { int ans=0; for(int i=2;i<=cnt;i+=2) e[i].w=1,e[i^1].w=0; while(bfs(x))ans+=dfs(S,1000000); return ans==x; } int main() { n=read();m=read(); for(int i=1;i<=n;i++)insw(S,i,1); for(int i=1;i<=m;i++)insw(read()+1,i+n,1),insw(read()+1,i+n,1),insw(i+n,T,1); int l=1,r=n,mid,ans=0; while(l<=r) { mid=(l+r)>>1;if(check(mid))ans=mid,l=mid+1; else r=mid-1; } cout<<ans; return 0; }