zoukankan      html  css  js  c++  java
  • 两道拟阵交水题

    题外话

    前几天nomama讲拟阵交,感觉自己跟不上时代了,学点新东西

    您打算学习的话,提个小建议:
    如果英文好的话,直接看《A Course in Combinatorial Optimization》
    如果英文不好,可以《浅谈拟阵的一些拓展及其应用》跟《A Course in Combinatorial Optimization》配合着看

    UVA12370 Game of Connect

    Shannon Switching Game

    做法

    定理( ext{color player})获胜的充要条件为存在两棵不交的生成树

    证明可以到google翻论文

    观察发现,可以转化为找图拟阵与"图拟阵的对偶拟阵"的拟阵交问题

    Code

    第一次打拟阵交,放份代码(uva上过了,但不清楚数据强度)

    #include<bits/stdc++.h>
    typedef int LL;
    typedef double dl;
    #define opt operator
    #define pb push_back
    #define pii std::pair<LL,LL>
    const LL maxn=3e2+9,mod=998244353,inf=0x3f3f3f3f;
    LL Read(){
    	LL x(0),f(1); char c=getchar();
    	while(c<'0' || c>'9'){
    		if(c=='-') f=-1; c=getchar();
    	}
    	while(c>='0' && c<='9'){
    		x=(x<<3ll)+(x<<1ll)+c-'0'; c=getchar();
    	}return x*f;
    }
    void Chkmin(LL &x,LL y){
    	if(y<x) x=y;
    }
    void Chkmax(LL &x,LL y){
    	if(y>x) x=y;
    }
    LL add(LL x,LL y){
    	return x+=y,x>=mod?x-mod:x;
    }
    LL dec(LL x,LL y){
    	return x-=y,x<0?x+mod:x;
    }
    LL mul(LL x,LL y){
    	return 1ll*x*y%mod;
    }
    LL Pow(LL base,LL b){
    	LL ret(1); while(b){
    		if(b&1) ret=mul(ret,base); base=mul(base,base); b>>=1;
    	}return ret;
    }
    namespace Uf{
    	LL N;
    	LL fa[maxn];
    	void Init(){
    		for(LL i=1;i<=N;++i) fa[i]=i;
    	}
    	LL Find(LL x){
    		return fa[x]==x?x:fa[x]=Find(fa[x]);
    	}
    	void Merge(LL x,LL y){
    		x=Find(x); y=Find(y);
    		if(x==y) return;
    		fa[x]=y;
    	}
    }
    struct edge{
    	LL x,y;
    };
    LL n,m,T,tim;
    LL X1[maxn],X2[maxn],dfn[maxn],low[maxn],mark[maxn];
    edge e[maxn];
    std::vector<pii> V[maxn];
    void Dfs(LL u,LL f){
    	dfn[u]=low[u]=++tim;
    	for(LL i=0;i<V[u].size();++i){
    		LL v(V[u][i].first),id(V[u][i].second);
    		if(v==f) continue;
    		if(!dfn[v]){
    			Dfs(v,u);
    			Chkmin(low[u],low[v]);
    			if(low[v]>dfn[u]){
    				X2[id]=0;
    			}
    		}else Chkmin(low[u],dfn[v]);
    	}
    }
    void Init_X1(){
    	Uf::Init();
    	for(LL i=1;i<=m;++i){
    		X1[i]=0;
    	}
    	for(LL i=1;i<=m;++i) if(mark[i]){
    		Uf::Merge(e[i].x,e[i].y);
    	}
    	for(LL i=1;i<=m;++i) if(!mark[i]){
    		if(Uf::Find(e[i].x)!=Uf::Find(e[i].y)){
    			X1[i]=1;
    		}
    	}
    }
    void Init_X2(){
    	Uf::Init();
    	for(LL i=1;i<=m;++i){
    		X2[i]=0;
    	}
    	for(LL i=1;i<=m;++i) if(!mark[i]){
    		Uf::Merge(e[i].x,e[i].y);
    	}
    	LL flag(1);
    	for(LL i=1;i<=n;++i){
    		flag&=(Uf::Find(i)==Uf::Find(1));
    	}
    	if(!flag) return;
    	for(LL i=1;i<=m;++i) if(!mark[i]){
    		X2[i]=1;
    	}
    	for(LL i=1;i<=n;++i){
    		std::vector<pii>().swap(V[i]);
    	}
    	for(LL i=1;i<=m;++i) if(!mark[i]){
    		LL x(e[i].x),y(e[i].y);
    		V[x].pb(pii(y,i)); V[y].pb(pii(x,i));
    	}
    	tim=0;
    	for(LL i=1;i<=n;++i){
    		dfn[i]=low[i]=0;
    	}
    	Dfs(1,0);
    }
    LL Solve(){
    	static LL pre[maxn],lu[maxn];
    	std::queue<LL> que;
    	Init_X1();
    	Init_X2();
    	for(LL i=1;i<=m;++i){
    		lu[i]=inf;
    	}
    	while(que.size()) que.pop();
    	for(LL i=1;i<=m;++i) if(!mark[i]){
    		if(X1[i]){
    			que.push(i);
    			lu[i]=0;
    		}
    	}
    	for(LL i=1;i<=m;++i){
    		pre[i]=0;
    	}
    	while(que.size()){
    		LL u(que.front()); que.pop();
    		if(X2[u]){
    			LL x(u);
    			while(x){
    				mark[x]^=1;
    				x=pre[x];
    			}
    			return 1;
    		}
    		if(mark[u]){
    			Uf::Init();
    			for(LL i=1;i<=m;++i) if(mark[i] && (i^u)){
    				Uf::Merge(e[i].x,e[i].y);
    			}
    			for(LL i=1;i<=m;++i) if(!mark[i] && lu[i]==inf){
    				if(Uf::Find(e[i].x)!=Uf::Find(e[i].y)){
    					pre[i]=u;
    					lu[i]=lu[u]+1;
    					que.push(i);
    				}
    			}
    		}else{
    			Uf::Init();
    			for(LL i=1;i<=m;++i) if(!mark[i] && (i^u)){
    				Uf::Merge(e[i].x,e[i].y);
    			}
    			LL comp(0);
    			for(LL i=1;i<=n;++i) comp+=(Uf::Find(i)==i);
    			for(LL i=1;i<=m;++i) if(mark[i] && lu[i]==inf){
    				if(comp==1 || (comp==2 && Uf::Find(e[i].x)!=Uf::Find(e[i].y))){
    					pre[i]=u;
    					lu[i]=lu[u]+1;
    					que.push(i);
    				}
    			}
    		}
    	}
    	return 0;
    }
    int main(){
    	T=Read();
    	for(LL ti=1;ti<=T;++ti){
    		printf("Case %d: ",ti);
    		n=Read(); m=Read();
    		for(LL i=1;i<=m;++i){
    			LL x(Read()+1),y(Read()+1);
    			e[i]=(edge){x,y};
    			mark[i]=0;
    		}
    		Uf::N=n;
    		Uf::Init();
    		for(LL i=1;i<=m;++i){
    			Uf::Merge(e[i].x,e[i].y);
    		}
    		LL flag(1);
    		for(LL i=1;i<=n;++i){
    			flag&=(Uf::Find(i)==Uf::Find(1));
    		}
    		if(!flag){
    			puts("NO");
    			continue;
    		}
    		LL num(0);
    		while(Solve()){
    			++num;
    		}
    		if(num==n-1) puts("YES");
    		else puts("NO");
    	}
    	return 0;
    }
    

    Rainbow Graph

    计蒜客

    做法

    (G_1)为Red边与Green边构成的图
    (G_2)为Green边与Blue边构成的图

    观察发现,可以将问题转化为(G_1)的对偶拟阵(G_2)的对偶拟阵的拟阵交问题

    如果这题延续上题,用tarjan判割边的方式写,代码量(5ksim 6k)

    但我们发现,这题的( ext{spfa})才是复杂度的瓶颈,故可以将上面tarjan判割边改成(O(m^2))( ext{dfs})做法,代码量(1ksim 2k)

  • 相关阅读:
    HDU_3127 WHUgirls(DP)
    ibatits
    jqGrid怎么设定水平滚动条
    poi导出EXcel
    jqGrid资料总结
    jqgrid横向滚动条
    开源网http://www.openopen.com/ajax/2_Charts.htm
    struts2国际化
    struts2结合poi导出excel
    Struts2 Action读取资源文件
  • 原文地址:https://www.cnblogs.com/Grice/p/14332785.html
Copyright © 2011-2022 走看看