这个就是完全按照论文中的做法来搞了,输出割边的时候就dfs判断一下在残余网络中该点是否可达汇点,不可达则是割边。
输出答案的证明可以百度到。
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- using namespace std;
- const int maxn=1e2+9,inf=1e9;
- const double epx=1e-6;
- int n,m;
- int d[maxn][maxn],level[maxn+1300],que[maxn+1300];
- int visit[maxn+1300];
- int S=0,T=1200;
- int head[maxn+1300],lon;
- struct
- {
- int next,to;
- double c;
- }e[111111];
- void edgeini()
- {
- memset(head,-1,sizeof(head));
- lon=-1;
- }
- void edgemake(int from,int to,double c)
- {
- e[++lon].c=c;
- e[lon].to=to;
- e[lon].next=head[from];
- head[from]=lon;
- }
- void makegraph(double ret)
- {
- edgeini();
- int tot=n;
- for(int i=1;i<=n;i++)
- {
- edgemake(i,T,ret);
- edgemake(T,i,0);
- }
- for(int i=1;i<=n;i++)
- for(int j=1;j<=n;j++)
- if(d[i][j])
- {
- ++tot;
- edgemake(S,tot,1);
- edgemake(tot,S,0);
- edgemake(tot,i,inf);
- edgemake(i,tot,0);
- edgemake(tot,j,inf);
- edgemake(j,tot,0);
- }
- }
- bool makelevel(int s,int t)
- {
- memset(level,0,sizeof(level));
- int front=1,end=0;
- que[++end]=s;
- level[s]=1;
- while(front<=end)
- {
- int u=que[front++];
- // cout<<u<<endl;
- if(u==t) return true;
- for(int k=head[u];k!=-1;k=e[k].next)
- {
- int v=e[k].to;
- if(e[k].c>0&&!level[v])
- {
- level[v]=level[u]+1;
- que[++end]=v;
- }
- }
- }
- return false;
- }
- double dfs(int now,int t,double maxf)
- {
- double ret=0;
- if(now==t) return maxf;
- for(int k=head[now];k!=-1;k=e[k].next)
- {
- int u=e[k].to;
- if(level[u]==level[now]+1&&e[k].c>0)
- {
- double f=dfs(u,t,min(maxf-ret,e[k].c));
- e[k].c-=f;
- e[k^1].c+=f;
- ret+=f;
- }
- }
- return ret;
- }
- double maxflow(int s,int t)
- {
- double ret=0;
- while(makelevel(s,t))
- {
- ret+=dfs(s,t,inf);
- }
- return ret;
- }
- bool chk()
- {
- double ans=maxflow(S,T);
- // cout<<m-ans<<endl;
- return (m-ans)>epx;
- }
- bool dfs(int now,int t)
- {
- // printf("%d %d\n",now,t);
- visit[now]=1;
- if(now==t) return true;
- for(int k=head[now];k!=-1;k=e[k].next)
- {
- int u=e[k].to;
- if(e[k].c>0&&!visit[u])
- if(dfs(u,t)) return true;
- }
- return false;
- }
- void prin()
- {
- // for(int i=0;i<=T;i++)
- // for(int k=head[i];k!=-1;k=e[k].next)
- if(e[k].c>0)
- // printf("%d %d %f\n",i,e[k].to,e[k].c);
- //
- // dfs(4,T);
- int sum=0;
- for(int i=1;i<=n;i++)
- {
- memset(visit,0,sizeof(visit));
- if(!dfs(i,T))
- {
- sum++;
- }
- }
- cout<<sum<<endl;
- for(int i=1;i<=n;i++)
- {
- memset(visit,0,sizeof(visit));
- if(!dfs(i,T))
- {
- printf("%d\n",i);
- }
- }
- }
- int main()
- {
- // freopen("in.txt","r",stdin);
- while(scanf("%d%d",&n,&m)!=EOF)
- {
- memset(d,0,sizeof(d));
- for(int i=1,from,to;i<=m;i++)
- {
- scanf("%d%d",&from,&to);
- d[from][to]=1;
- }
- double l=0,r=n,mid;
- while(r-l>epx)
- {
- mid=(l+r)/2;
- makegraph(mid);
- // cout<<mid<<endl;
- if(chk()) l=mid;
- else r=mid;
- //prin();
- }
- // printf("%f\n",epx);
- // cout<<l<<endl;
- makegraph(l);
- chk();
- prin();
- }
- return 0;
- }