楼教主论文里的题
这么多剪枝吓坏我了
忽然想起来我WC的时候第一题前两个点也是搜索+最大流,不知道能不能剪枝把后面的数据水过去呢233333然而并不能想到什么剪枝
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; vector<int>g[105]; bool vis[105],can[105][105][105]; int maxl[105],dist[105],S[105],T[105],ans,mag[105],n,m,maxt[105][105]; bool match(int u){ for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(!vis[v]){ vis[v]=true; if(!S[v]||match(S[v])){ S[v]=u; T[u]=v; return true; } } } return false; } void addnode(int s,int t,int x){ for(int i=1;i<=n;i++) if(can[s][t][i])g[x].push_back(i); } void dfs(int x,int pos){ if(x+dist[pos]-1>=ans)return; if(pos>m){ ans=x-1; for(int i=1;i<=x;i++)mag[i]=T[i]; return; } for(int i=maxl[pos];i>=pos;i--){ g[x].clear(); addnode(pos,i,x); memset(vis,0,sizeof(vis)); if(match(x))dfs(x+1,i+1); S[T[x]]=0; T[x]=0; } } int x[105],y[105],u[105],v[105],k; int sqr(int x){return x*x;} void pre(){ for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) can[i][i][j]=sqr(x[i]-u[j])+sqr(y[i]-v[j])<=sqr(k); for(int i=1;i<=m;i++) for(int j=i+1;j<=m;j++) for(int k=1;k<=n;k++) can[i][j][k]=can[i][j-1][k]&&can[j][j][k]; memset(dist,0x3f,sizeof(dist)); dist[m+1]=0; for(int i=m;i>=1;i--) for(int j=m+1;j>i;j--) for(int k=1;k<=n;k++) if(can[i][j-1][k])dist[i]=min(dist[i],dist[j]+1); for(int i=1;i<=n;i++){ maxt[i][m+1]=m; for(int j=m;j>=1;j--) if(can[j][j][i])maxt[i][j]=maxt[i][j+1]; else maxt[i][j]=j-1; } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++) maxl[i]=max(maxl[i],maxt[j][i]); maxl[i]=max(maxl[i],i); } } int main(){ //freopen("a.in","r",stdin); scanf("%d%d%d",&m,&n,&k); for(int i=1;i<=m;i++)scanf("%d%d",&x[i],&y[i]); for(int i=1;i<=n;i++)scanf("%d%d",&u[i],&v[i]); pre(); ans=10000000; dfs(1,1); printf("%d\n",ans); for(int i=1;i<=ans;i++) printf("%d ",mag[i]); return 0; }