• 【JZOJ4672】Graph Coloring【模拟】【搜索】


    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/4672
    现在你有一张无向图包含nn个节点mm条边。最初,每一条边都是蓝色或者红色。每一次你可以将一个节点连接的所有边变色(从红变蓝,蓝变红)。
    找到一种步数最小的方案,使得所有边的颜色相同。


    思路:

    记得以前做过费解的开关这道题,发现两道题蛮像的。
    于是就用同样的思路去思考。
    可以考虑先枚举其中一个点选择或不选择,以及最终要改成哪个颜色。如果我们已经把一条边上一个点修改了,那么如果要把这条边再次改回来,就只能把两另外一个点选择。但是你选择了这个点之后,又会有新的边被修改,然后依次类推。
    所以,可以用一遍搜索来处理。如果经过若干次修改之后全部边都变成了一个颜色,那么就更新答案。


    代码:

    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    const int N=100010;
    const int Inf=1e9;
    int n,m,x,y,ans1,ans2,tot=1,head[N],father[N];
    bool vis[N],used[N];
    char ch;
    
    struct edge
    {
    	int next,to,col;
    }e[N*2],a[N*2],b[N*2];
    
    int find(int x)
    {
    	return x==father[x]?x:father[x]=find(father[x]);
    }
    
    void add(int from,int to,int c)
    {
    	e[++tot].to=to;
    	e[tot].col=c;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    bool check(int col)
    {
    	for (register int i=2;i<=tot;i++)
    		if (a[i].col!=col) return 0;
    	return 1;
    }
    
    int work1(int S,int col,int change)
    {
    	memset(vis,0,sizeof(vis));
    	queue<int> q;
    	vis[S]=1;
    	int cnt=change;
    	for (register int i=head[S];~i;i=a[i].next)
    	{
    		if (change)
    			a[i].col^=1,a[i^1].col^=1;
    		q.push(i);
    	}
    	while (q.size())
    	{
    		int j=q.front();
    		q.pop();
    		int u=a[j].to;
    		vis[u]=1;
    		if (a[j].col!=col)
    		{
    			cnt++;
    			for (register int i=head[u];~i;i=a[i].next)
    			{
    				a[i].col^=1;
    				a[i^1].col^=1;
    				int v=a[i].to;
    				if (vis[v]&&a[i].col!=col)
    					return Inf;
    				if (!vis[v]) q.push(i);
    			}
    		}
    		else
    		{
    			for (register int i=head[u];~i;i=a[i].next)
    			{
    				int v=a[i].to;
    				if (vis[v]&&a[i].col!=col)
    					return Inf;
    				if (!vis[v]) q.push(i);
    			}
    		}
    	}
    	return cnt;
    }
    
    int work2(int S,int col,int change)
    {
    	memset(vis,0,sizeof(vis));
    	queue<int> q;
    	vis[S]=1;
    	int cnt=change;
    	for (register int i=head[S];~i;i=b[i].next)
    	{
    		if (change)
    			b[i].col^=1,b[i^1].col^=1;
    		q.push(i);
    	}
    	while (q.size())
    	{
    		int j=q.front();
    		q.pop();
    		int u=b[j].to;
    		vis[u]=1;
    		if (b[j].col!=col)
    		{
    			cnt++;
    			for (register int i=head[u];~i;i=b[i].next)
    			{
    				b[i].col^=1;
    				b[i^1].col^=1;
    				int v=b[i].to;
    				if (vis[v]&&b[i].col!=col)
    					return Inf;
    				if (!vis[v]) q.push(i);
    			}
    		}
    		else
    		{
    			for (register int i=head[u];~i;i=b[i].next)
    			{
    				int v=b[i].to;
    				if (vis[v]&&b[i].col!=col)
    					return Inf;
    				if (!vis[v]) q.push(i);
    			}
    		}
    	}
    	return cnt;
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for (register int i=1;i<=n;i++)
    		father[i]=i;
    	for (register int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		father[find(x)]=find(y);
    		while ((ch=getchar())&&ch!='R'&&ch!='B') ;
    		if (ch=='R')
    		{
    			add(x,y,1);
    			add(y,x,1);
    		}
    		else
    		{
    			add(x,y,0);
    			add(y,x,0);
    		}
    	}
    	memcpy(a,e,sizeof(e));
    	memcpy(b,e,sizeof(e));
    	for (register int i=1;i<=n;i++)
    		if (!used[find(i)])
    		{
    			int fa=find(i);
    			used[fa]=1;
    			ans1+=min(work1(fa,1,0),work2(fa,1,1));
    			if (ans1>=Inf) break;
    		}
    	memset(used,0,sizeof(used));
    	memcpy(a,e,sizeof(e));
    	memcpy(b,e,sizeof(e));
    	for (register int i=1;i<=n;i++)
    		if (!used[find(i)])
    		{
    			int fa=find(i);
    			used[fa]=1;
    			ans2+=min(work1(fa,0,0),work2(fa,0,1));
    			if (ans2>=Inf) break;
    		}
    	if (ans1>=Inf&&ans2>=Inf) printf("-1");
    		else printf("%d",min(ans1,ans2));
    	return 0;
    }
    
  • 相关阅读:
    Educational Codeforces Round 74 (Rated for Div. 2)
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) 题解
    D
    Card Hand Sorting 二进制枚举暴力
    20172018-acmicpc-southeastern-european-regional-programming-contest-seerc-2017-en A
    Round #590 (Div. 3)
    A
    P2634 [国家集训队]聪聪可可
    HDU-4807-Lunch Time(二分+费用流,思维)
    易错分析
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998279.html
Copyright © 2020-2023  润新知