• BZOJ.4500.矩阵(差分约束 SPFA判负环 / 带权并查集)


    BZOJ


    差分约束:

    我是谁,差分约束是啥,这是哪

    太真实了= =  插个广告:这里有差分约束详(并不)解

    (r_i)为第(i)行整体加了多少的权值,(c_i)为第(i)列整体加了多少权值,那么限制((i,j),k)就是(r_i+c_j=k)
    这就是差分约束裸题了。(r_i+c_j=kRightarrow r_i-(-c_j)leq k && -c_j-r_ileq -k)
    注意形式是(x_j-x_ileq w)=v=
    建边跑最短路判负环即可。

    去洛谷复习以前的板子(忘了怎么写了=-=),发现DFS判负环被卡掉了?太棒啦不用背DFS的代码惹。
    乖乖写BFS好了。


    带权并查集:
    发现这题和BZOJ1202是一模一样的= =。因为全是相等关系,其实是十分特殊的差分约束,可以用带权并查集做。
    (fa[x])表示(x)所在集合的根节点,(dis[x])表示(x)(fa[x])的实际距离。
    所谓距离是指:对于(r+c=k),变成(r-(-c)=k),即(r)(-c)(k),就在(r o -c)之间连距离为(k)的边,同时令(fa[r]=-c)
    这样对于一个限制(r,c,k),如果(r,c)不在同一集合就合并(令较大的数的祖先是较小的数)。在并查集(Find)过程中顺便维护一下(dis)(具体见代码好惹,注意变量赋值顺序)。
    如果(r,c)在同一集合,就根据(dis)差判一下它俩的距离是否等于(k)

    就算(k)可能是负的这么做也没什么问题。(废话=v=)


    差分约束:

    //904kb	48ms
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    const int N=2005;
    
    int Enum,H[N],nxt[N],to[N],len[N],dis[N],dgr[N];
    bool vis[N],inq[N];
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now*f;
    }
    inline void AE(int u,int v,int w)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w;
    }
    bool SPFA(int s,int n)//怎么都直接拿n做总点数的=-= 强迫症表示不行 
    {
    	std::queue<int> q;
    	q.push(s), dis[s]=0;
    	while(!q.empty())
    	{
    		int x=q.front(); q.pop();
    		inq[x]=0;
    		for(int i=H[x],v; i; i=nxt[i])
    			if(dis[v=to[i]]>dis[x]+len[i])
    			{
    				if(++dgr[v]>n) return 1;
    				dis[v]=dis[x]+len[i], !inq[v]&&(q.push(v),inq[v]=1);
    			}
    	}
    	return 0;
    }
    
    int main()
    {
    	for(int Ts=read(); Ts--; )
    	{
    		int n=read(),m=read(),tot=n+m,cnt=0;
    		Enum=0, memset(H,0,tot+1<<2), memset(vis,0,tot+1);
    		for(int u,v,w,K=read(); K--; )
    		{
    			u=read(),v=read()+n,w=read();
    			AE(v,u,w), AE(u,v,-w);
    			if(!vis[u]) vis[u]=1, ++cnt;
    			if(!vis[v]) vis[v]=1, ++cnt;
    		}
    		memset(dis,0x7f,tot+1<<2), memset(dgr,0,tot+1<<2), memset(inq,0,tot+1);
    		bool fg=1;
    		for(int i=1; i<=tot; ++i)
    			if(vis[i]&&dis[i]==dis[0]&&SPFA(i,cnt)) {fg=0; break;}
    		puts(fg?"Yes":"No");
    	}
    
    	return 0;
    }
    

    带权并查集:

    //836kb	20ms
    #include <cstdio>
    #include <cctype>
    #include <assert.h>
    #include <algorithm>
    #define gc() getchar()
    typedef long long LL;
    const int N=2005;
    
    int fa[N],dis[N];
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now*f;
    }
    int Find(int x)
    {
    	if(x==fa[x]) return x;
    	int t=fa[x];
    	fa[x]=Find(t), dis[x]+=dis[t];//!!!
    	return fa[x];
    }
    
    int main()
    {
    	for(int Ts=read(); Ts--; )
    	{
    		const int n=read(),m=read(),tot=n+m;
    		for(int i=1; i<=tot; ++i) fa[i]=i, dis[i]=0;
    		bool fg=1;
    		for(int u,v,w,K=read(); K--; )
    		{
    			u=read(),v=read()+n,w=read();
    			if(!fg) continue;
    			int r1=Find(u),r2=Find(v);
    			if(r1!=r2) fa[r1]=r2, dis[r1]=dis[v]+w-dis[u];
    			else if(dis[u]-dis[v]!=w) fg=0;
    		}
    		puts(fg?"Yes":"No");
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    CentOS7 mysql5.7安装并配置主主同步
    CentOS7 jdk安装
    CentOS7 zabbix安装并实现其它服务器服务监控报警与自动恢复
    CentOS7 SkyWalking APM8.1.0 搭建与项目集成使用
    Centos7 搭建DNS服务器
    mybatis中collection association优化使用及多参数传递
    mysql常用配置注意项与sql优化
    Spring webFlux:坐等spring-boot-starter-data-mysql-reactive
    ElasticSearch 工具类封装(基于ElasticsearchTemplate)
    接口配置有效管理(获取配置文件内容3种常见方式)
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10755363.html
Copyright © 2020-2023  润新知