Luo Gu 5295 [Beijing Provincial Election Training 2019] Figure puzzles

Blog viewing effect is better

Brief description of the title

Give you an undirected graph with \ (n \) points \ (m \) edges to determine whether some edges can be dyed white, others dyed black, and there is no solid color ring.

\ (n \ le 501, m \ le 2n \)

Ideas

A picture has \ (E \) edges and \ (V \) points. Then, it must satisfy the ring without solid color, the maximum value of \ (E \) is \ (2 (V-1) \) (in this case, white and black form two spanning trees respectively).

\ (E \ le 2V-2 \) , can become \ (E-2V \ le -2 \) .

Then all of our current graphs must satisfy the conditions, and of course any of the subgraphs also satisfy the conditions. We can convert: \ (E-2V \) the largest subgraph and also meet \ (E-2V \ Le -2 \) .

How to find the largest subgraph of \ (E-2V \) ? Think of edges as points and points as edges. This becomes the maximum weight closed subgraph problem.

(No Baidu)

Code

#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
	#define N 100055
	#define INF 0x5f5f5f5f
	#define F(i,l,r) for(int i=l;i<=r;++i)
	#define D(i,r,l) for(int i=r;i>=l;--i)
	#define Fs(i,l,r,c) for(int i=l;i<=r;c)
	#define Ds(i,r,l,c) for(int i=r;i>=l;c)
	#define MEM(x,a) memset(x,a,sizeof(x))
	#define FK(x) MEM(x,0)
	#define Tra(i,u) for(int i=G.Start(u),v=G.To(i);~i;i=G.Next(i),v=G.To(i))
	#define p_b push_back
	#define sz(a) ((int)a.size())
	#define iter(a,p) (a.begin()+p)
	int I()
	{
	    int x=0;char c=getchar();int f=1;
	    while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
	    while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	    return (x=(f==1)?x:-x);
	}
	void Rd(int cnt,...)
	{
	    va_list args; va_start(args,cnt);
	    F(i,1,cnt) {int* x=va_arg(args,int*);(*x)=I();}
	    va_end(args);
	}
	class Graph
	{
	    public:
	        int EdgeCount;
	        int head[N];
	        int To[N],Label[N],Next[N];

	        inline void clear()
	        {
	            MEM(head,-1);
	            EdgeCount=-1;
	        }
	        inline void AddEdge(int u,int v,int w)
	        {
	            ++EdgeCount;
	            To[EdgeCount]=v; Label[EdgeCount]=w; Next[EdgeCount]=head[u];
	            head[u]=EdgeCount;
	        }
	
	        int Source,Sink;
	        int deep[N];
	        queue<int> Q;
	        bool BFS()
	        {
	            while(!Q.empty()) Q.pop();
	            FK(deep);
	
	            Q.push(Source);
	            deep[Source]=1;
	            do
	            {
	                int u=Q.front();Q.pop();
	                for(register int i=head[u];~i;i=Next[i])
	                {
	                    int v=To[i];
	                    if (!deep[v] and Label[i])
	                    {
	                        deep[v]=deep[u]+1;
	                        if (v==Sink) {return true;}
	                        Q.push(v);
	                    }
	                }
	            }while(!Q.empty());
	
	            return (bool)(deep[Sink]);
	        }
	        int DFS(int u,int MinFlow)
	        {
	            if (u==Sink) return MinFlow;

	            int rest=MinFlow;
	            for(register int i=head[u];~i and rest;i=Next[i])
	            {
	                int v=To[i];
	                if (deep[v]==deep[u]+1 and Label[i]!=0)
	                {
	                    int d=DFS(v,min(MinFlow,Label[i]));
	                    if (!d) deep[v]=0;
                        Label[i]-=d;
                        Label[i^1]+=d;
                        rest-=d;
	                }
	            }
	            return MinFlow-rest;
	        }
	        int Dinic()
	        {
	            int ans=0;
	            while(BFS()) ans+=DFS(Source,INF);
	            return ans;
	        }
	}Nt; // 网络流
	
	int n,m;
	int uu[N],vv[N];
	void Input()
	{
		Rd(2,&n,&m);
		F(i,1,m) uu[i]=I(),vv[i]=I();
	}

	#define S Nt.Source
	#define T Nt.Sink
	#define AddFlow(u,v,w) {Nt.AddEdge(u,v,w); Nt.AddEdge(v,u,0);}
    // 建流
	int MustChoose(int s) // 强制选择点 s 的答案
	{
		Nt.clear();
		F(i,1,m) 
		{
			int u=uu[i],v=vv[i];
			AddFlow(S,i,1);
			AddFlow(i,m+u,INF);
			AddFlow(i,m+v,INF);
		}
		F(i,1,n) if (i!=s)
		{
			AddFlow(i+m,T,2);
		}

		return m-2-Nt.Dinic();
	}
	void Soviet()
	{
		S=n+m+1,T=n+m+2;
		int ans=-INF;
		F(i,1,n) 
		{
			ans=max(ans,MustChoose(i)); // 把每个强制选 i 的答案取 max,就是最大闭合子图了
			if (ans>-2) {puts("No"); return;} // 每一个都要 <=-2,有一个 > 就直接输出 No
		}
		
		puts((ans<=-2)?"Yes":"No");
	}

	#define Flan void
	Flan IsMyWife()
	{
		int t=I();
		F(i,1,t)
		{
			Input();
			Soviet();
		}
	}
}
int main()
{
	Flandre_Scarlet::IsMyWife();
	getchar();getchar();
	return 0;
}

Guess you like

Origin www.cnblogs.com/LightningUZ/p/12681819.html