• 洛谷P3275 [SCOI2011]糖果(差分约束,最长路,Tarjan,拓扑排序)


    洛谷题目传送门

    差分约束模板题,等于双向连0边,小于等于单向连0边,小于单向连1边,我太蒻了,总喜欢正边权跑最长路。。。。。。

    看遍了讨论版,我是真的不敢再入复杂度有点超级伪的SPFA的坑了

    为了保证复杂度,需要缩点后用拓扑排序统计答案。首先全相等的点本质上是相同的,可以缩到一起,所以先来一波Tarjan把0环全缩起来。接着再考虑边权为1的边。如果这时候还出现了环(包括缩点以后的自环),一定是不存在方案的,这是可以用拓扑排序判断。否则,就是个DAG,拓扑排序也可以直接计算出答案。

    统计答案要注意:因为缩了点,所以答案要乘上超级点的size;因为每个小朋友都要有糖,所以最后答案+n(或者也可以将虚点的d值初始化为1,只不过最后要减掉1)

    我不会说我连Tarjan都不会写调了半个下午的

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define I inline
    #define R register
    #define G ch=getchar()
    #define REP for(i=1;i<=n;++i)
    #define add(L,X,Y)
    	l[++p]=L;to[p]=Y;
    	ne[p]=he[X];he[X]=p;
    	if(!tl[X])tl[X]=p//鬼畜tl指向链表尾部,方便链表合并
    const int N=100009,M=N*3;
    int p,df,tot,he[N],tl[N],ne[M],to[M],rd[N],d[N],low[N],dfn[N],sz[N],f[N],st[N];
    bool l[M];
    template<typename T>
    I void in(R T&z){
    	R char G;
    	while(ch<'-')G;
    	z=ch&15;G;
    	while(ch>'-')z*=10,z+=ch&15,G;
    }
    void tarjan(R int x){
    	low[st[++p]=x]=dfn[x]=++df;
    	for(R int y,i=he[x];i;i=ne[i]){
    		if(l[i])continue;//只能缩0环
    		if(!dfn[y=to[i]]){
    			tarjan(y);
    			low[x]=min(low[x],low[y]);
    		}
    		else if(!f[y])low[x]=min(low[x],dfn[y]);
    	}
    	if(low[x]==dfn[x]){
    		++tot;
    		do ++sz[f[st[p]]=x];
    		while(st[p--]!=x);
    	}
    }
    int main(){
    	R int p=0,n,k,S,o,x,y,i,j,cnt=0;
    	in(n);in(k);S=n+1;
    	R long long ans=n;//好像
    	while(k--){
    		in(o);in(x);in(y);
    		switch(o){
    			case 1:add(0,x,y);add(0,y,x);break;
    			case 2:add(1,x,y);break;
    			case 3:add(0,y,x);break;
    			case 4:add(1,y,x);break;
    			case 5:add(0,x,y);
    		}
    	}
    	for(i=1;i<=n;++i){add(0,S,i);}//虚点搞上
    	tarjan(S);
    	for(i=1;i<=S;++i){
    		x=f[i];
    		for(j=he[i];j;j=ne[j]){
    			y=to[j]=f[to[j]];//改一下
    			if(x!=y)++rd[y];//在新图上统计入度
    			else if(l[j]){puts("-1");return 0;}//自环可以直接判掉
    		}
    	}
    	for(i=1;i<=S;++i)//合并链表
        	if(i!=f[i])ne[tl[i]]=he[f[i]],he[f[i]]=he[i];
    	st[p=1]=S;
    	while(p){
    		++cnt;//统计进入拓扑排序的总点数
    		ans+=d[x=st[p--]]*sz[x];
    		for(i=he[x];i;i=ne[i]){
    			y=to[i];
    			d[y]=max(d[y],d[x]+l[i]);
    			if(!--rd[y])st[++p]=y;
    		}
    	}
    	printf("%lld
    ",cnt<tot?-1:ans);
    	return 0;
    }
    
  • 相关阅读:
    包括”/“排除”设置禁用了加载功能。
    如何打造高质量的机器学习数据集?
    机器学习项目流程(一)初探数据集
    java 转义与反转义
    jfinal 获取刚保存的对象的主键 ,该主键在数据库中自增
    凤凰架构:构建可靠的大型分布式系统 ISBN:9787111683919 -推荐
    STC89C52控制74HC595,74HC138双色16x16点阵屏循环显示汉字
    STC89C52驱动MAX7219LED点阵级联, 文字滚动效果
    STM32F407VET6烧录出现flash download failed target dll has been cancelled
    DS1302与STC12的连接电路和驱动实现
  • 原文地址:https://www.cnblogs.com/flashhu/p/8670817.html
Copyright © 2020-2023  润新知