CF652E Pursuit For Artifacts

CF652E Pursuit For Artifacts

题目链接
先来一发吐槽:
这道题先搞了个结构体把当前每个点属于的编号和缩点后的权值搞在了一起,然后成功把自己搞昏 我不管我一定要骂自己是sb!我是最瓜的!
教训:做题之前好好理思路,建议把代码名称代表的东西理清楚,写代码的时候遇到也要多想想 不然就像今天,从中午调到晚上TATawsl
思路:

  1. 从起点到终点连一条边(证明:如果原来在,不影响;如果原来不在,但中间有权值为1的割边,连虚边之后则处于一个联通块;如果原来不在且中间没有权值为1的割边(但有割边),则还需判断分别所属联通块有没有1;如果原来不在且虚边为割边,恭喜凉凉;)
  2. t a r j a n tarjan 找到当前图所有割边
  3. d f s dfs 找每一个 e D C C e-DCC
  4. m a i n main 函数里遍历每一条边,如果不是桥边,则更新当前 e D C C e-DCC 的值
  5. 判断是否符合题意,输出

几点注意:

  1. 缩点完了再合并权值,边有可能没有遍历完,dfs时只是把每个点遍历了一次
  2. 运算符优先级(图源百度) ( m < < 1 1 ) (m<<1|1) 打括号,位运算符优先级在比较符号之后
    在这里插入图片描述
  3. 慎用结构体,一定要理清楚每个变量代表的意义

上代码时间到!

#include <bits/stdc++.h>
using namespace std;
const int N=6e5+50;
int t,n,m;
int dis[N<<1],to[N<<1],nxt[N<<1],val[N<<1],dfn[N],low[N],w[N],tot,fir[N],num;
int wei[N];
struct node{
	int id;
}c[N];
int dcc,bridge[N<<1];
void add(int x,int y,int z){nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;val[tot]=z;}
void clear(){
	tot = 1;
	memset(dis,0,sizeof(dis));
	memset(bridge,0,sizeof(bridge));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));
	memset(c,0,sizeof(c));
	num=0;dcc=0;memset(fir,0,sizeof(fir));
	memset(wei,0,sizeof(wei));
	
}
void dfs(int x){//找e-DCC 
	c[x].id=dcc;
	for(int i=fir[x];i;i=nxt[i]){
		if(bridge[i])	continue;
		int y=to[i];
		if(c[y].id)	continue;
		dfs(y);
	}
}
void tarjan(int x,int in_edge){//找割边 
	dfn[x]=low[x]=++num;
	for(int i=fir[x];i;i=nxt[i]){
		int y=to[i];
		if(!dfn[y]){
			tarjan(y,i);
			low[x]=min(low[x],low[y]);
			if(low[y]>dfn[x]){
				bridge[i]=bridge[i^1]=true;
			}
		}
		else{
			if(i!=(in_edge^1)){
				low[x]=min(low[x],dfn[y]);
			}
		}
	}
}
inline int read(){
	int cnt=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-'){f=-f;}c=getchar();}
	while(isdigit(c)){cnt=(cnt<<3)+(cnt<<1)+(c^48);c=getchar();}
	return cnt*f;
}
int main(){
	t=read();
	while(t--){
		num=0;
		n=read(),m=read();clear();
		for(int i=1;i<=m;i++){
			int x,y,z;
			x=read(),y=read(),z=read();
			add(x,y,z);add(y,x,z);
		}
		int st,ed;st=read(),ed=read();
		add(st,ed,0);add(ed,st,0);
		//cout<<n<<" "<<m<<endl;
		for(int i=1;i<=n;i++){
			if(!dfn[i])	tarjan(i,0); 
		}
		for(int i=1;i<=n;i++){
			if(!c[i].id){
				++dcc;dfs(i);//找e-DCC
			}
			//cout<<c[i].wei<<endl;
		}
		for(int i=2;i<=(m<<1|1);i++){
			if(!bridge[i]){
				wei[c[to[i]].id]|=val[i];
			}
		}
		if(c[st].id==c[ed].id&&wei[c[st].id]>=1){
			printf("YES\n");
		}
		else{
			printf("NO\n");
		}
	}	
	return 0;
}
发布了37 篇原创文章 · 获赞 11 · 访问量 1947

猜你喜欢

转载自blog.csdn.net/weixin_42750325/article/details/102555860