zoukankan      html  css  js  c++  java
  • codeforces786E ALT【倍增+最小割】

    方案二选一,显然是最小割,朴素的想法就是一排人点一排边点,分别向st连流量1的边,然后人点向路径上的边点连流量inf的边跑最大流
    但是路径可能很长,这样边数就爆了,所以考虑倍增,然后倍增后大区间向小区间连,这样路径只要连向log个区间就行了,然后跑最大流
    输出方案是在残量网络上从s点沿着没满流的边bfs,因为满流的边一定在最小割里,所以没有访问到的人点和访问到的边点就是能得到宠物的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    const int N=400005;
    int n,m,h[N],cnt,p[N],le[N],si[N],hs[N],fa[N],de[N],fr[N],s,t,id[N][16],tot,f[N][16];
    vector<int>a1,a2;
    struct qwe
    {
    	int ne,to,va;
    }e[N*20];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void ade(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    void dfs1(int u,int fat)
    {
    	fa[u]=f[u][0]=fat;
    	si[u]=1;
    	de[u]=de[fat]+1;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fat)
    		{
    			p[e[i].to]=e[i].va;
    			dfs1(e[i].to,u);
    			si[u]+=si[e[i].to];
    			if(si[e[i].to]>si[hs[u]])
    				hs[u]=e[i].to;
    		}
    }
    void dfs2(int u,int top)
    {
    	fr[u]=top;
    	if(!hs[u])
    		return;
    	dfs2(hs[u],top);
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa[u]&&e[i].to!=hs[u])
    			dfs2(e[i].to,e[i].to);
    }
    int lca(int u,int v)
    {
    	for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);
    	return de[u]<de[v]?u:v;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    void ins(int u,int v,int w)
    {//cerr<<u<<" "<<v<<"  "<<w<<endl;
    	add(u,v,w);
    	add(v,u,0);
    }
    bool bfs()
    {
    	memset(le,0,sizeof(le));
    	queue<int>q;
    	q.push(s);
    	le[s]=1;
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		for(int i=h[u];i;i=e[i].ne)
    			if(e[i].va&&!le[e[i].to])
    			{
    				le[e[i].to]=le[u]+1;
    				q.push(e[i].to);
    			}
    	}
    	return le[t];
    }
    int dfs(int u,int f)
    {
    	if(u==t||!f)
    		return f;
    	int us=0;
    	for(int i=h[u];i&&us<f;i=e[i].ne)
    		if(e[i].va&&le[e[i].to]==le[u]+1)
    		{
    			int t=dfs(e[i].to,min(e[i].va,f-us));
    			e[i].va-=t;
    			e[i^1].va+=t;
    			us+=t;
    		}
    	if(!us)
    		le[u]=0;
    	return us;
    }
    int dinic()
    {
    	int r=0;
    	while(bfs())
    		r+=dfs(s,1e9);
    	return r;
    }
    void wk(int x,int lc,int i)
    {
    	int z=fa[fr[x]];
    	while(x!=z&&de[x]>de[lc])
    		ins(i,x+m,1e9),x=fa[x];//,cerr<<1<<" "<<x<<endl;
    	while(de[fr[x]]>de[lc])
    		ins(i,fr[x]+n+m,1e9),x=fa[fr[x]];//,cerr<<2<<" "<<x<<endl;
    	while(de[x]>de[lc])
    		ins(i,x+m,1e9),x=fa[x];
    }
    int main()
    {
    	n=read(),tot=m=read();
    	for(int i=1;i<n;i++)
    	{
    		int x=read(),y=read();
    		ade(x,y,i),ade(y,x,i);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	memset(h,0,sizeof(h));
    	cnt=1;
    	for(int i=1;i<=n;i++)
    		id[i][0]=++tot;
    	for(int j=1;j<=15;j++)
    		for(int i=1;i<=n;i++)
    		{
    			f[i][j]=f[f[i][j-1]][j-1];
    			if(i!=1)
    				id[i][j]=++tot;
    			if(id[i][j-1])
    				ins(id[i][j],id[i][j-1],1e9);
    			if(id[f[i][j-1]][j-1])
    				ins(id[i][j],id[f[i][j-1]][j-1],1e9);
    		}
    	s=0,t=tot+1;
    	for(int i=2;i<=n;i++)
    		ins(id[i][0],t,1);
    	for(int i=1;i<=m;i++)
    	{
    		ins(s,i,1);
    		int x=read(),y=read(),lc=lca(x,y);
    		if(de[x]>de[y])
    			swap(x,y);
    		for(int d=de[y]-de[x],k=15,t=(1<<15);d;k--,t/=2)
    			if(d>=t)
    			{
    				d-=t;
    				ins(i,id[y][k],1e9);
    				y=f[y][k];
    			}
    		if(x!=y)
    		{
    			for(int k=15;k>=0;k--)
    				if(f[x][k]!=f[y][k])
    				{
    					ins(i,id[x][k],1e9);
    					ins(i,id[y][k],1e9);
    					x=f[x][k],y=f[y][k];
    				}
    			ins(i,id[x][0],1e9);
    			ins(i,id[y][0],1e9);
    		}
    	}
    	printf("%d
    ",dinic());
    	memset(le,0,sizeof(le));
    	queue<int>q;
    	q.push(s);
    	le[s]=1;
    	while(!q.empty())
    	{
    		int u=q.front();//cerr<<u<<endl;
    		q.pop();
    		for(int i=h[u];i;i=e[i].ne)
    			if(!le[e[i].to]&&e[i].va>0)
    			{
    				le[e[i].to]=1;
    				q.push(e[i].to);
    			}
    	}
    	for(int i=1;i<=m;i++)
    		if(!le[i])
    			a1.push_back(i);
    	for(int i=2;i<=n;i++)
    		if(le[i+m])
    			a2.push_back(p[i]);
    	printf("%d ",a1.size());
    	for(int i=0;i<a1.size();i++)
    		printf("%d ",a1[i]);
    	puts("");
    	printf("%d ",a2.size());
    	for(int i=0;i<a2.size();i++)
    		printf("%d ",a2[i]);
    	return 0;
    }
    
  • 相关阅读:
    Good Bye 2014 B. New Year Permutation(floyd )
    hdu 5147 Sequence II (树状数组 求逆序数)
    POJ 1696 Space Ant (极角排序)
    POJ 2398 Toy Storage (叉积判断点和线段的关系)
    hdu 2897 邂逅明下 (简单巴什博弈)
    poj 1410 Intersection (判断线段与矩形相交 判线段相交)
    HDU 3400 Line belt (三分嵌套)
    Codeforces Round #279 (Div. 2) C. Hacking Cypher (大数取余)
    Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings (容斥原理)
    hdu 1576 A/B (求逆元)
  • 原文地址:https://www.cnblogs.com/lokiii/p/11001914.html
Copyright © 2011-2022 走看看