| ||||||||||
| 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