题意:有很多联系方式要分组,每个联系方式可以分到若干个组去,问最多的那组最少会有多少联系方式。
思路:稍想了一下,就想到了二分枚举答案,然后看最大流是否等于n,然后取最小的输出。一开始TLE,后来改成手写队列,然后wa,后来发现打错一个字母,然后过了。
瞎想:坚持了这么久的EK算法,我想迟早逃脱不了TLE的命运,是不是该学习新的算法了呢?
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int m,n,s,t,fst[2000],next[600000],node[600000],c[600000]; int en,f[600000],h[505],hnum,pre[2000],lu[2000]; bool vis[2000]; char str[30]; void init() { en=0; hnum=0; memset(fst,-1,sizeof(fst)); } void add(int u,int v,int cc) { next[en]=fst[u]; fst[u]=en; node[en]=v; c[en]=cc; en++; } void change(int cc) { for(int i=0;i<hnum;i++) { c[h[i]]=cc; } } bool bfs() { memset(vis,0,sizeof(vis)); int q[2000]; int front=0,end=0; q[end++]=s; vis[s]=1; while(front<end) { int u=q[front++]; for(int i=fst[u];i!=-1;i=next[i]) { int v=node[i]; if(!vis[v]&&c[i]>f[i]) { pre[v]=u; lu[v]=i; vis[v]=1; if(v==t)return true; q[end++]=v; } } } return false; } int ek() { int flow=0; memset(f,0,sizeof(f)); while(bfs()) { for(int i=t;i!=s;i=pre[i]) { int v=lu[i]; f[v]+=1; f[v^1]-=1; } flow+=1; } return flow; } void solve() { int ans=n; int left=1,right=n,mid; while(left<=right) { mid=(left+right)/2; change(mid); if(ek()==n) { ans=min(mid,ans); right=mid-1; } else { left=mid+1; } } cout<<ans<<endl; } int main() { int u; while(scanf("%d%d",&n,&m)) { if(m==0&&n==0)break; init(); s=0; t=m+n+2; for(int i=1;i<=n;i++) { scanf("%s",str); while(getchar()!='\n') { scanf("%d",&u); add(i,u+n+1,1); add(u+n+1,i,0); } add(0,i,1); add(i,0,0); } for(int i=0;i<m;i++) { h[hnum++]=en; add(n+i+1,t,1); add(t,n+i+1,0); } solve(); } return 0; }