zoukankan      html  css  js  c++  java
  • LOJ3462. 「WC2021」括号路径

    一张图,给出若干个三元组((u,v,w)),表示有(u o v)的颜色为(w)的左括号和(v o u)的颜色为(w)的右括号。询问多少对((u,v),u<v)使得(u)(v)存在路径使得这个路径上的括号序合法。

    (nle 3*10^5,mle 6*10^5)


    在比赛最后一个小时前一直在想怎么前缀和不小于零……于是连暴力都不会写……

    后来忽然发现可以记(f_{u,v})表示(u)可以到(v),然后暴力扩展。估分32,实际水了48。

    比赛之后才发现这个东西是双向的,也就是说(f_{u,v}=f_{v,u})

    于是如果(f_{u,v}=1),可以把(u,v)看成等价类。

    用并查集+启发式合并维护搞出所有等价类即可。

    具体:把等价类缩点,并且记录这些点的每种颜色的入边。把点丢到一个队列里,操作某个点的时候,找到所有入边大于等于(2)的边,将这些边连向的点缩起来,然后丢到队列中。

    注意细节。


    using namespace std;
    #include <bits/stdc++.h>
    #define N 300005
    #define M 600005
    #define ll long long
    int n,m,k;
    int dsu[N];
    int getdsu(int x){return dsu[x]==x?x:dsu[x]=getdsu(dsu[x]);}
    map<int,vector<int> > e[N];
    set<int> b[N];
    int sz[N];
    queue<int> q;
    bool inq[N];
    vector<int> o[N]; 
    bool cmpo(int x,int y){return sz[x]>sz[y];}
    void merge(int x,int y){
    	for (auto i=e[y].begin();i!=e[y].end();++i){
    		auto t=&e[x][i->first];
    		for (auto j=i->second.begin();j!=i->second.end();++j)
    			t->push_back(*j);
    		if (t->size()>=2)
    			b[x].insert(i->first);
    	}
    	e[y].clear();
    	dsu[y]=x;
    	sz[x]+=sz[y];
    }
    void BFS(){
    	for (int i=1;i<=n;++i)
    		q.push(i),inq[i]=1;
    	while (!q.empty()){
    		int x=q.front();
    		q.pop();
    		inq[x]=0;
    		x=getdsu(x);
    		int cnt=0;
    		for (auto i=b[x].begin();i!=b[x].end();++i){
    			auto t=&e[x][*i];
    			for (auto j=t->begin();j!=t->end();++j)
    				o[cnt].push_back(*j);
    			cnt++;
    			for (int j=t->size();j>=2;--j)
    				t->pop_back();
    		}
    		b[x].clear();
    		static int bz[N],BZ;
    		for (int i=0;i<cnt;++i){
    			++BZ;
    			int mx=0;
    			for (int j=0;j<o[i].size();++j){
    				int y=getdsu(o[i][j]);
    				if (sz[y]>sz[mx]) mx=y;
    			}
    			for (int j=0;j<o[i].size();++j){
    				int y=getdsu(o[i][j]);
    				if (y==mx) continue;
    				merge(mx,y);
    			}
    			if (!inq[mx])
    				inq[mx]=1,q.push(mx);
    			o[i].clear();
    		}
    	}
    }
    int main(){
    	freopen("in.txt","r",stdin);
    //	freopen("out.txt","w",stdout);
    	scanf("%d%d%d",&n,&m,&k);	
    	sz[0]=-1;
    	for (int i=1;i<=n;++i)
    		dsu[i]=i;
    	for (int i=1;i<=m;++i){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		e[v][w].push_back(u);
    		if (e[v][w].size()==2)
    			b[v].insert(w);
    		sz[v]++;
    	}
    	BFS();
    	static int cnt[N];
    	ll ans=0;
    	for (int i=1;i<=n;++i)
    		cnt[getdsu(i)]++;
    	for (int i=1;i<=n;++i)
    		if (dsu[i]==i)
    			ans+=(ll)cnt[i]*(cnt[i]-1)>>1;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/jz-597/p/14390911.html
Copyright © 2011-2022 走看看