zoukankan      html  css  js  c++  java
  • 【XSY1762】染色问题 网络流

    题目描述

      给定一张(n)个点(m)条边的无向图。每个顶点有一个颜色,要么是黑,要么是白。我们想进行一些操作,使得最终每一条边的两个端点都是不同的颜色。每一次操作,你可以将一条边的两个端点交换颜色。求最少的操作次数和具体的操作方式。

      (nleq 500)

    题解

      首先黑白染色,假设要让染出来的黑点最终成为黑点,那么

       1.对于原来的每个黑点(i),连边((S,i,1,0))

       2.对于染出来的每个黑点(i),连边((i,T,1,0))

       3.对于原图中的每条边((u,v)),连边((u,v,infty,1),(v,u,infty,1)),表示交换两个端点的花费。

      跑完费用流后,每次bfs找到一条从(S)(T)的路径,通过某些方法交换第一个点和最后一个点。

      对于一条长度大于(1)的路径,第一个点一定是白色的,最后一个点一定是黑色的。(第一个点靠(T),最后一个点靠(S)

      

      先把这个序列切成很多段,每段只有最右边的点是黑色的。

      

      把每段的黑点调到最前面

      

      再从后往前交换每段的第一个点和前一段的最后一个点。

      

      这样可以用长度(-1)步内交换第一个点和最后一个点。

      时间复杂度:(O(???))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<queue>
    #include<list>
    #include<vector>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    queue<int> q;
    //vector<pii> a;
    int ax[1000010];
    int ay[1000010];
    int len=0;
    struct li
    {
    	int h[510];
    	int v[100010];
    	int t[100010];
    	int n;
    	li()
    	{
    		memset(h,0,sizeof h);
    		n=0;
    	}
    	void add(int x,int y)
    	{
    		n++;
    		v[n]=y;
    		t[n]=h[x];
    		h[x]=n;
    	}
    };
    li l;
    struct graph
    {
    	int h[510];
    	int u[500010];
    	int v[500010];
    	int w[500010];
    	int c[500010];
    	int t[500010];
    	int p[500010];
    	int n;
    	void clear()
    	{
    		n=0;
    		memset(h,0,sizeof h);
    	}
    	void add(int x,int y,int z,int d)
    	{
    		n++;
    		u[n]=x;
    		v[n]=y;
    		w[n]=d;
    		c[n]=z;
    		p[n]=0;
    		t[n]=h[x];
    		h[x]=n;
    	}
    	int S,T;
    	int gd[510];
    	int gb[510];
    	int gf[510];
    	int flow,cost;
    	int f[510];
    	int op(int x)
    	{
    		return ((x-1)^1)+1;
    	}
    	int spfa()
    	{
    		memset(gd,0x7f,sizeof gd);
    		gd[S]=0;
    		gf[S]=0;
    		q.push(S);
    		int i,x;
    		while(!q.empty())
    		{
    			x=q.front();
    			q.pop();
    			gb[x]=0;
    			if(gd[x]>=gd[T])
    				continue;
    			for(i=h[x];i;i=t[i])
    				if(c[i]&&gd[v[i]]>gd[x]+w[i])
    				{
    					gd[v[i]]=gd[x]+w[i];
    					gf[v[i]]=i;
    					if(!gb[v[i]])
    					{
    						gb[v[i]]=1;
    						q.push(v[i]);
    					}
    				}
    		}
    		if(gd[T]==0x7f7f7f7f)
    			return 0;
    		flow++;
    		cost+=gd[T];
    		for(i=gf[T];i;i=gf[u[i]])
    		{
    			c[i]--;
    			p[i]++;
    			c[op(i)]++;
    			p[op(i)]--;
    		}
    		return 1;
    	}
    	int maxflow()
    	{
    		flow=cost=0;
    		while(spfa());
    		return cost;
    	}
    	int p1[500010];
    	int p2[500010];
    	void check()
    	{
    		memset(gb,0,sizeof gb);
    		gb[S]=1;
    		gf[S]=0;
    		q.push(S);
    		int i;
    		while(!q.empty())
    		{
    			int x=q.front();
    			q.pop();
    			for(i=h[x];i;i=t[i])
    				if(p[i]&&!gb[v[i]])
    				{
    					gb[v[i]]=1;
    					gf[v[i]]=i;
    					if(v[i]==T)
    					{
    						while(!q.empty())
    							q.pop();
    						return;
    					}
    					q.push(v[i]);
    				}
    		}
    	}
    	void getans()
    	{
    		check();
    		int i;
    		int t1=0,t2=0;
    		for(i=gf[T];i;i=gf[u[i]])
    		{
    			if(v[i]!=T)
    				p1[++t1]=v[i];
    			p[i]--;
    		}
    		for(i=t1;i>=2;i--)
    			if(f[p1[i-1]])
    				p2[++t2]=i;
    			else
    			{
    //				a.push_back(pii(p1[i-1],p1[i]));
    				ax[++len]=p1[i-1];
    				ay[len]=p1[i];
    				swap(f[p1[i]],f[p1[i-1]]);
    			}
    		for(i=t2;i>=1;i--)
    		{
    //			a.push_back(pii(p1[p2[i]],p1[p2[i]-1]));
    			ax[++len]=p1[p2[i]];
    			ay[len]=p1[p2[i]-1];
    			swap(f[p1[p2[i]]],f[p1[p2[i]-1]]);
    		}
    	}
    };
    graph g1,g2;
    char s[510];
    int c[510];
    int from[510][510];
    int d[510][510];
    int vis[100010];
    int s1,s2;
    int b,w;
    int ans;
    list<int> e,e1,e2;
    void failed()
    {
    	printf("-1
    ");
    	exit(0);
    }
    void dfs(int x,int p)
    {
    	if(~vis[x])
    	{
    		if(vis[x]!=p)
    			failed();
    		return;
    	}
    	e.push_back(x);
    	vis[x]=p;
    	if(c[x])
    		b++;
    	else
    		w++;
    	if(p)
    	{
    		s1++;
    		e1.push_back(x);
    	}
    	else
    	{
    		s2++;
    		e2.push_back(x);
    	}
    	int i;
    	for(i=l.h[x];i;i=l.t[i])
    		dfs(l.v[i],p^1);
    }
    int build1()
    {
    	for(auto v1:e)
    	{
    		int i;
    		for(i=l.h[v1];i;i=l.t[i])
    		{
    			int v2=l.v[i];
    			g1.add(v1,v2,1000,1);
    			g1.add(v2,v1,0,-1);
    			g1.add(v2,v1,1000,1);
    			g1.add(v1,v2,0,-1);
    		}
    		if(c[v1])
    		{
    			g1.add(g1.S,v1,1,0);
    			g1.add(v1,g1.S,0,0);
    		}
    	}
    	for(auto v1:e2)
    	{
    		g1.add(v1,g1.T,1,0);
    		g1.add(g1.T,v1,0,0);
    	}
    	return g1.maxflow();
    }
    int build2()
    {
    	for(auto v1:e)
    	{
    		int i;
    		for(i=l.h[v1];i;i=l.t[i])
    		{
    			int v2=l.v[i];
    			g2.add(v1,v2,1000,1);
    			g2.add(v2,v1,0,-1);
    			g2.add(v2,v1,1000,1);
    			g2.add(v1,v2,0,-1);
    		}
    		if(c[v1])
    		{
    			g2.add(g2.S,v1,1,0);
    			g2.add(v1,g2.S,0,0);
    		}
    	}
    	for(auto v1:e1)
    	{
    		g2.add(v1,g2.T,1,0);
    		g2.add(g2.T,v1,0,0);
    	}
    	return g2.maxflow();
    }
    void rd(int &s)
    {
    	int c;
    	while((c=getchar())<'0'||c>'9');
    	s=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    		s=s*10+c-'0';
    }
    int main()
    {
    	int n,m;
    //	scanf("%d%d",&n,&m);
    	rd(n);
    	rd(m);
    	int i;
    	scanf("%s",s+1);
    	for(i=1;i<=n;i++)
    		c[i]=s[i]-'0';
    	int x,y;
    	for(i=1;i<=m;i++)
    	{
    //		scanf("%d%d",&x,&y);
    		rd(x);
    		rd(y);
    		l.add(x,y);
    		l.add(y,x);
    	}
    	memset(vis,-1,sizeof vis);
    	ans=0;
    	g1.S=g2.S=n+1;
    	g1.T=g2.T=n+2;
    	for(i=1;i<=n;i++)
    		if(vis[i]==-1)
    		{
    			w=b=s1=s2=0;
    			e.clear();
    			e1.clear();
    			e2.clear();
    			dfs(i,0);
    			if(w!=s1&&w!=s2)
    				failed();
    			int ans1=0x7fffffff,ans2=0x7fffffff;
    			g1.clear();
    			g2.clear();
    			int f1,f2;
    			if(w==s1&&b==s2)
    			{
    				ans1=build1();
    				f1=g1.flow;
    			}
    			if(b==s1&&w==s2)
    			{
    				ans2=build2();
    				f2=g2.flow;
    			}
    			if(ans1<ans2)
    			{
    				ans+=ans1;
    				memcpy(g1.f,c,sizeof c);
    				while(f1--)
    					g1.getans();
    			}
    			else
    			{
    				ans+=ans2;
    				memcpy(g2.f,c,sizeof c);
    				while(f2--)
    					g2.getans();
    			}
    		}
    	printf("%d
    ",ans);
    //	for(auto v:a)
    //		printf("%d %d
    ",v.first,v.second);
    	for(i=1;i<=len;i++)
    		printf("%d %d
    ",ax[i],ay[i]);
    	return 0;
    }
    
  • 相关阅读:
    JavaScript
    94.Binary Tree Inorder Traversal
    144.Binary Tree Preorder Traversal
    106.Construct Binary Tree from Inorder and Postorder Traversal
    105.Construct Binary Tree from Preorder and Inorder Traversal
    90.Subsets II
    78.Subsets
    83.Merge Sorted Array
    80.Remove Duplicates from Sorted Array II
    79.Word Search
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8511233.html
Copyright © 2011-2022 走看看