您的位置:首页 > 其它

洛谷 P3731 [HAOI2017]新型城市化

2018-03-15 17:43 369 查看

题目

原题链接

给定一张图,这张图最多有两个团,求增加一条边使得最大团变大。

分析

再也不乱给边加上界了啊啊啊啊!!!

这张图的补图一定是二分图。

其中最大团就是最大独立集。

最大独立集就是结点数-最大流

我们要最大流减少

所以我们要找最小割

按照BZOJ 1797: [Ahoi2009]Mincut 最小割(我的博客)第一问的方法判断一个结点是否是一种最小割里面的一个点就可以了。

二分图千万反向边千万不要偷懒使得上界和正向边相同。

网络流都不要偷懒乱加上界!

代码

#include<cmath>
#include<queue>
#include<cctype>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=10000+105,maxm=15e4+105,inf=1e8;
int np,first[maxn];
struct edge{
int from,to,next,cap,flow;
}E[maxm<<1];
void add(int u,int v,int c)
{
E[++np]=(edge){u,v,first[u],c,0};
first[u]=np;
}
int n,m,s,t;
void Init()
{
int u,v;
np=-1;
memset(first,-1,sizeof(first));
scanf("%d%d",&n,&m);
s=n+1,t=s+1;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v,1);
add(v,u,1);
}
}
int dist[maxn],gap[maxn];
int SAP(int i,int lim)
{
if(i==t)return lim;
int flow=0,tmp;
for(int p=first[i];p!=-1;p=E[p].next)if(E[p].cap-E[p].flow)
{
int j=E[p].to;
if(dist[i]==dist[j]+1)
{
tmp=SAP(j,min(lim-flow,E[p].cap-E[p].flow));
E[p].flow+=tmp;
E[p^1].flow-=tmp;
flow+=tmp;
if(dist[s]>=t || lim==flow)return flow;
}
}
if(flow==0)
{
if(--gap[dist[i]]==0)dist[s]=t;
gap[++dist[i]]++;
}
return flow;
}
void maxFlow()
{
memset(gap,0,sizeof(gap));
memset(dist,0,sizeof(dist));
gap[0]=t;
while(dist[s]<t)SAP(s,inf);
}
int stk[maxn],top;
int dfs_clock,scc,belong[maxn],low[maxn],dfn[maxn];
void DFS(int i)
{
stk[++top]=i;
dfn[i]=low[i]=++dfs_clock;
for(int p=first[i];p!=-1;p=E[p].next)
{
if(E[p].cap-E[p].flow)
{
int j=E[p].to;
if(belong[j])continue;
if(dfn[j])
{
low[i]=min(low[i],low[j]);
continue;
}
DFS(j);
low[i]=min(low[j],low[i]);
}
}
if(dfn[i]==low[i])
{
int x;
scc++;
while(1)
{
x=stk[top--];
belong[x]=scc;
if(x==i)break;
}
}
}
void tarjian()
{
for(int i=1;i<=t;i++)
if(!dfn[i])DFS(i);
}
struct data
{
int i,j;
friend bool operator<(data a,data b)
{
return a.i!=b.i?a.i<b.i:a.j<b.j;
}
void outs()
{
printf("%d %d\n",i,j);
}
}ans[maxn];
int cnt;
void query()
{
for(int i=1;i<=n;i++)
{
for(int p=first[i];p!=-1;p=E[p].next)
{
if(E[p].flow)
{
int j=E[p].to;
if(j<i)continue;
if(j==s || j==t)continue;
if(belong[i] != belong[j])
ans[++cnt]=(data){i,j};
}
}
}
sort(ans+1,ans+cnt+1);
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
ans[i].outs();
}
bool vis[maxn],co[maxn];
void DFS(int i,bool c)
{
co[i]=c;
vis[i]=1;
if(c)
{
add(s,i,1);
add(i,s,0);
}
else
{
add(i,t,1);
add(t,i,0);
}
for(int p=first[i];p!=-1;p=E[p].next)
{
int j=E[p].to;
if(vis[j] || j==s || j==t)continue;
DFS(j,c^1);
}
}
void erfen()
{
for(int i=1;i<=n;i++)if(!vis[i])DFS(i,1);
for(int i=1;i<=m;i++)
{
int j=E[(i-1)*2].to;
(!co[E[(i-1)*2].from] && co[j])?E[(i-1)*2].cap=0:E[((i-1)*2)^1].cap=0;
}
}
int main()
{
//freopen("in.txt","r",stdin);
Init();
erfen();
maxFlow();
tarjian();
query();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: