Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
不需要卡精度1、注意此题网络流中ans=n*m-c[s,t],因为c[s,t]是<=n*m,也就是说ans=f(g)>=0(此时|V|=0),那么f(g)不再单调递减,而是到了0后,一直为0。 2、可以证明,1/n^2的二分精度就可以了, 设g为最优解,g1为其他解中任意一个,我们现在要证明【g-1/n^2,g】这个区间中的数(设为g2)对应的方案都是最优解的方案。 由论文可得:g1<=g2<=g,此时最优解|E|-g2|V|>=0,其他解|E1|-g2|V1|<=0 也就是说f(g2)所对应的最大方案仍旧是最优解,证毕。 附上我的代码: //我同时乘上了n^2,变成了整型 # include<iostream> using namespace std; const int maxn=108,maxm=4008,oo=2147483647; int a[maxm],next[maxm],start[maxn],tot,n,m,S,T,in[maxn],level[maxn],h[maxn],now[maxn],dfn[maxn]; int c[maxm]; struct arr { int x,y; }b[maxm]; void Init() { scanf("%d%d",&n,&m); int i; for (i=1;i<=m;i++) { scanf("%d%d",&b[i].x,&b[i].y); in[b[i].x]++;in[b[i].y]++; } S=0;T=n+1; } void Add(int x,int y,int z,int t) { a[++tot]=y;next[tot]=start[x];start[x]=tot;c[tot]=z; a[++tot]=x;next[tot]=start[y];start[y]=tot;if (t) c[tot]=z;else c[tot]=0; } void Make_map(int g) { memset(start,0,(T+1)<<2);tot=1; int i; for (i=1;i<=m;i++) Add(b[i].x,b[i].y,n*n,1); for (i=1;i<=n;i++) {Add(S,i,m*n*n,0);Add(i,T,2*g+(m-in[i])*n*n,0);} } bool Bfs() { int l=1,r=0; memset(level,0,(T+1)<<2); memcpy(now,start,(T+1)<<2); h[++r]=S;level[S]=1; while (l<=r) { int u=h[l]; for (int i=start[u];i;i=next[i]) { int v=a[i]; if (c[i]&&level[v]==0) { level[v]=level[u]+1;h[++r]=v; if (v==T) return 1; } } ++l; } return 0; } int Dinic(int u,int l) { if (u==T) return l; int t=l; for (now[u];now[u];now[u]=next[now[u]]) { int i=now[u]; int v=a[i]; if (c[i]==0||level[v]!=level[u]+1) continue; int tmp=Dinic(v,min(c[i],l)); c[i]-=tmp;c[i^1]+=tmp;l-=tmp; if (l==0) break; } if (t==l) level[u]=-1; return t-l; } int F(int g) { Make_map(g); int ans=0; while (Bfs()) ans+=Dinic(S,oo); return n*m*n*n-ans; } void Dfs(int u) { dfn[u]=1; for (int i=start[u];i;i=next[i]) { int v=a[i]; if (c[i]&&dfn[v]==0) Dfs(v); } } void Work() { int l=n,r=m*n*n; int ans=0; while (l<=r) { int mid=l+r>>1; int k=F(mid); if (k>0) {ans=max(mid,ans);l=mid+1;}else r=mid-1; } if (m==0) printf("%d\n%d\n",1,1); else { F(ans); memset(dfn,0,(T+1)<<2); Dfs(S);tot=0; for (int i=1;i<=n;i++) if (dfn[i]) tot++; printf("%d\n",tot); for (int i=1;i<=n;i++) if (dfn[i]) printf("%d\n",i); } } int main() { Init(); Work(); return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator