• noi.ac NA537 【Graph】


    本来以为过了...然后FST了...

    吐槽:nmdGraph为什么不连通...

    这题想法其实非常(naddot{imath}ve),就是对于一个连通块先钦点一个点为根,颜色是(1),考虑到边权限制点权,可以做二分图染色,钦点连通块内的某个形如树形的边的子集是全部合法的,显然一棵树是一定有解的,对于此时的(min ,max)只需要看根节点的取值范围取(min ,max),对于图的话显然就是多了一些边,判断多的边两端节点是否同色,如果同色则意味着根节点的权值是唯一确定的,如果不是整数则无解,否则直接赋值重跑一遍计算(ans)即可,复杂度(mathcal{O}(n+m))

    因为代码是从FST的改过来的,memset其实会T,但是懒得改了,所以下面代码复杂度是假的,不过不影响正确性

    #include<bits/stdc++.h>
    #define yes printf("%lld %lld
    ",ansa,ansb);exit(0)
    #define no printf("NIE
    ");exit(0)
    #define int long long
    
    using namespace std;
    
    signed ch;
    
    void qread(int &xx){
    	xx=0;ch=getchar();
    	while(!isdigit(ch)){
    		ch=getchar();
    	}
    	while(isdigit(ch)){
    		xx=xx*10+ch-'0';
    		ch=getchar();
    	}
    }
    
    const int N=5e5+5,M=6e6+6;
    
    int n,m,ans,ansa,ansb,p[N],vis[N];
    
    int fir[N],nxt[M],to[M],edge[M],cntedge,col[N],c[N],cnt[3];
    
    int mi[3]={0,0,0x3f3f3f3f},up[3]={0,0,0x3f3f3f3f};
    
    void addedge(int u,int v,int w){
    	++cntedge;to[cntedge]=v;edge[cntedge]=w;nxt[cntedge]=fir[u];fir[u]=cntedge;
    }
    
    namespace subtree{
    	queue<int>q;
    	void bfs(int u){
    		for(int now=fir[u],v;now;now=nxt[now]){
    			v=to[now];
    			if(col[v]){
    				continue;
    			}
    			c[v]=edge[now]-c[u];
    			col[v]=3-col[u];
    			++cnt[col[v]];
    			ans+=c[v];
    			mi[col[v]]=min(mi[col[v]],c[v]);
    			up[col[v]]=min(up[col[v]],p[v]-c[v]);
    			q.push(v);
    		}
    	}
    	void solve(){
    		q.push(1);col[1]=1;++cnt[1];up[1]=p[1];
    		while(!q.empty()){
    			int u=q.front();q.pop();
    			bfs(u);
    		}
    		if(up[1]+up[2]<0){
    			no;
    		}
    		if(up[1]<0){
    			for(int i=1;i<=n;i++){
    				col[i]==1?(c[i]+=up[1],ans+=up[1]):(c[i]-=up[1],ans-=up[1]);
    			}
    			up[2]+=up[1];mi[2]-=up[1];mi[1]+=up[1];up[1]=0;
    		}
    		if(up[2]<0){
    			for(int i=1;i<=n;i++){
    				col[i]==2?(c[i]+=up[2],ans+=up[2]):(c[i]-=up[2],ans-=up[2]);
    			}
    			up[1]+=up[2];mi[1]-=up[2];mi[2]+=up[2];up[2]=0;
    		}
    		if(mi[1]+up[2]<0||mi[2]+up[1]<0||mi[1]+mi[2]<0){
    			no;
    		}
    		if(mi[1]<0){
    			for(int i=1;i<=n;i++){
    				col[i]==1?c[i]-=mi[1],ans-=mi[1]:c[i]+=mi[1],ans+=mi[1];
    			}
    			up[2]+=mi[1];mi[2]+=mi[1];up[1]+=mi[1];mi[1]=0;
    		}
    		else if(mi[2]<0){
    			for(int i=1;i<=n;i++){
    				col[i]==2?c[i]-=mi[2],ans-=mi[2]:c[i]+=mi[2],ans+=mi[2];
    			}
    			up[1]+=mi[2];mi[1]+=mi[2];up[2]+=mi[2];mi[2]=0;
    		}
    		if(cnt[1]==cnt[2]){
    			ansa=ansb=ans;
    		}
    		else if(cnt[1]<cnt[2]){
    			ansa=ans-min(mi[2],up[1])*(cnt[2]-cnt[1]);
    			ansb=ans+min(mi[1],up[2])*(cnt[2]-cnt[1]);
    		}
    		else{
    			ansa=ans-min(mi[1],up[2])*(cnt[1]-cnt[2]);
    			ansb=ans+min(mi[2],up[1])*(cnt[1]-cnt[2]);
    		}
    		yes;
    	}
    }
    
    namespace qwq{
    	queue<int>q;
    	int s,id=0;bool flag;
    	bool check(){
    		while(!q.empty()){
    			q.pop();
    		}
    		memset(col,0,sizeof col);
    		q.push(s);col[s]=1;ans=c[s];
    		while(!q.empty()){
    			int u=q.front();q.pop();
    			vis[u]=id;
    			if(c[u]<0||c[u]>p[u]){
    				no;
    			}
    			for(int now=fir[u],v;now;now=nxt[now]){
    				v=to[now];
    				if(col[v]){
    					if(c[u]+c[v]!=edge[now]){
    						no;
    					}
    					continue;
    				}
    				c[v]=edge[now]-c[u];
    				col[v]=3-col[u];
    				ans+=c[v];
    				q.push(v);
    			}
    		}
    		ansa+=ans;ansb+=ans;
    		return 1;
    	}
    	void bfs(int u){
    		vis[u]=id;
    		for(int now=fir[u],v;now;now=nxt[now]){
    			v=to[now];
    			if(col[v]){
    				if(col[u]^col[v]){
    					if(c[u]+c[v]!=edge[now]){
    						no;
    					}
    				}
    				else{
    					if(((c[u]+c[v])&1)^(edge[now]&1)){
    						no;
    					}
    					if(col[u]^2){
    						c[s]=(edge[now]-c[u]-c[v])>>1;
    						if(check()){
    							flag=1;return;
    						}
    						else{
    							no;
    						}
    					}
    					else{
    						c[s]=(c[u]+c[v]-edge[now])>>1;
    						if(check()){
    							flag=1;return;
    						}
    						else{
    							no;
    						}
    					}
    				}
    				continue;
    			}
    			c[v]=edge[now]-c[u];
    			col[v]=3-col[u];
    			++cnt[col[v]];
    			ans+=c[v];
    			mi[col[v]]=min(mi[col[v]],c[v]);
    			up[col[v]]=min(up[col[v]],p[v]-c[v]);
    			q.push(v);
    		}
    	}
    	void work(){
    		while(!q.empty()){
    			q.pop();
    		}
    		flag=0;
    		memset(cnt,0,sizeof cnt);
    		up[2]=mi[2]=0x3f3f3f3f;mi[1]=0;
    		q.push(s);col[s]=1;++cnt[1];up[1]=p[s];ans=0;
    		while(!q.empty()){
    			int u=q.front();q.pop();bfs(u);
    		}
    		if(flag){
    			return;
    		}
    		if(up[1]+up[2]<0){
    			no;
    		}
    		if(up[1]<0){
    			for(int i=1;i<=n;i++){
    				if(vis[i]!=id){
    					continue;
    				}
    				col[i]==1?(c[i]+=up[1],ans+=up[1]):(c[i]-=up[1],ans-=up[1]);
    			}
    			up[2]+=up[1];mi[2]-=up[1];mi[1]+=up[1];up[1]=0;
    		}
    		if(up[2]<0){
    			for(int i=1;i<=n;i++){
    				if(vis[i]!=id){
    					continue;
    				}
    				col[i]==2?(c[i]+=up[2],ans+=up[2]):(c[i]-=up[2],ans-=up[2]);
    			}
    			up[1]+=up[2];mi[1]-=up[2];mi[2]+=up[2];up[2]=0;
    		}
    		if(mi[1]+up[2]<0||mi[2]+up[1]<0||mi[1]+mi[2]<0){
    			no;
    		}
    		if(mi[1]<0){
    			for(int i=1;i<=n;i++){
    				if(vis[i]!=id){
    					continue;
    				}
    				col[i]==1?c[i]-=mi[1],ans-=mi[1]:c[i]+=mi[1],ans+=mi[1];
    			}
    			up[2]+=mi[1];mi[2]+=mi[1];up[1]+=mi[1];mi[1]=0;
    		}
    		else if(mi[2]<0){
    			for(int i=1;i<=n;i++){
    				if(vis[i]!=id){
    					continue;
    				}
    				col[i]==2?c[i]-=mi[2],ans-=mi[2]:c[i]+=mi[2],ans+=mi[2];
    			}
    			up[1]+=mi[2];mi[1]+=mi[2];up[2]+=mi[2];mi[2]=0;
    		}
    		if(cnt[1]==cnt[2]){
    			ansa+=ans;ansb+=ans;
    		}
    		else if(cnt[1]<cnt[2]){
    			ansa+=ans-min(mi[2],up[1])*(cnt[2]-cnt[1]);
    			ansb+=ans+min(mi[1],up[2])*(cnt[2]-cnt[1]);
    		}
    		else{
    			ansa+=ans-min(mi[1],up[2])*(cnt[1]-cnt[2]);
    			ansb+=ans+min(mi[2],up[1])*(cnt[1]-cnt[2]);
    		}
    	}
    	void solve(){
    		for(int i=1;i<=n;i++){
    			if(!vis[i]){
    				++id;s=i;
    				work();
    			}
    		}
    		yes;
    	}
    }
    
    signed main(){
    	qread(n);qread(m);
    	for(int i=1;i<=n;i++){
    		qread(p[i]);
    	}
    	for(int i=1,u,v,w;i<=m;i++){
    		qread(u);qread(v);qread(w);addedge(u,v,p[u]+p[v]-w);addedge(v,u,p[u]+p[v]-w);
    	}
    	if(n==m+1){
    		subtree::solve();
    	}
    	else{
    		qwq::solve();
    	}
    	no;
    	return 0;
    }
    
  • 相关阅读:
    C#之纯数字判断
    C#之仿魔兽登录
    jQuery考试之错题分析
    初学jQuery之jQuery虚假购物车-------与真实数据无关
    Jquery中绑定事件的异同
    总结java基础
    初学jQuery之jQuery事件与动画
    初学jQuery之jQuery选择器
    JavaScript 实现复制到剪贴板的总结
    IE和其他浏览器的表现差异:盒子间的空隙,图片变形,justify-content无效
  • 原文地址:https://www.cnblogs.com/--BLUESKY007/p/11146569.html
Copyright © 2020-2023  润新知