zoukankan      html  css  js  c++  java
  • #Tarjan,SPFA,差分约束系统#BZOJ 2330 AcWing 368 银河

    题目


    分析

    首先这明显是一道差分约束题,但是无解的情况确实比较恶心,

    考虑它的边权为0或1,无解当且仅当某个强连通分量内的边至少一条边边权为1,

    那么用有向图的Tarjan缩点后跑SPFA就可以了


    代码

    #include <cstdio>
    #include <cctype>
    #include <stack>
    #include <cstring>
    #include <queue>
    #define rr register
    using namespace std;
    const int N=100011; stack<int>stac; queue<int>q;
    struct node{int y,w,next;}e[N*3],E[N*3];
    int dfn[N],low[N],v[N],dis[N],hs[N],col[N];
    int siz[N],as[N],cnt,tot,et,Et,n,m; long long ans;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void add(int x,int y,int w){E[++Et]=(node){y,w,hs[x]},hs[x]=Et;}
    inline signed min(int a,int b){return a<b?a:b;}
    inline void tarjan(int x){
    	dfn[x]=low[x]=++tot,
    	stac.push(x),v[x]=1;
    	for (rr int i=hs[x];i;i=E[i].next)
    	if (!dfn[E[i].y]){
    		tarjan(E[i].y);
    		low[x]=min(low[x],low[E[i].y]);
    	}else if (v[E[i].y])
    	    low[x]=min(low[x],dfn[E[i].y]);
    	if (dfn[x]==low[x]){
    		rr int y; ++cnt;
    		do{
    			y=stac.top(); stac.pop();
    			col[y]=cnt,v[y]=0,++siz[cnt];
    		}while (x^y);
    	}
    }
    signed main(){
    	n=iut()+1; m=iut();
    	for (rr int i=1;i<n;++i) add(n,i,1);
    	for (rr int i=1;i<=m;++i){
    		rr int z=iut(),x=iut(),y=iut();
    		switch (z){
    			case 1:{
    				add(x,y,0),add(y,x,0);
    				break;
    			}
    			case 2:{
    				add(x,y,1);
    				break;
    			}
    			case 3:{
    				add(y,x,0);
    				break;
    			}
    			case 4:{
    				add(y,x,1);
    				break;
    			}
    			case 5:{
    				add(x,y,0);
    				break;
    			}
    		}
    	}
    	for (rr int i=1;i<=n;++i)
    	    if (!dfn[i]) tarjan(i);
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=hs[i];j;j=E[j].next)
    	if (col[i]^col[E[j].y])
    		e[++et]=(node){col[E[j].y],E[j].w,as[col[i]]},as[col[i]]=et; 
    	else if (E[j].w) return !printf("-1");
    	memset(dis,0xcf,sizeof(dis));
    	q.push(col[n]),v[col[n]]=1,dis[col[n]]=0;
    	while (!q.empty()){
    		rr int x=q.front(); q.pop();
    		for (rr int i=as[x];i;i=e[i].next)
    		if (dis[e[i].y]<dis[x]+e[i].w){
    			dis[e[i].y]=dis[x]+e[i].w;
    			if (!v[e[i].y]) v[e[i].y]=1,q.push(e[i].y);
    		}
    		v[x]=0;
    	}
    	for (rr int i=1;i<=cnt;++i) ans+=siz[i]*dis[i];
    	return !printf("%lld",ans);
    }
    
  • 相关阅读:
    tp5.1接入支付宝网站支付
    go类型转换
    mysql常见sql练习题
    php 获取当前时间的 前一小时、一天、一个月、一年
    php如何检测是否有环
    Go的切片:长度和容量
    go实现小项目
    知乎网页版不登录如何浏览内容
    图挂了
    centos搭建php环境
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13928524.html
Copyright © 2011-2022 走看看