zoukankan      html  css  js  c++  java
  • 【欧拉路径-Hierholzer算法】组合-NOIp模拟赛T1

    题目链接

    题目解析

    简单理解一下题意,发现题意就是尾字母和首字母相同的两个长度为(2)的单词可以拼在一起,问是否能把所有的单词拼成一个长串。

    把字母看成点,容易发现一个单词描述了一条有向边,而题目要求就是问你是否有一条路径,每条边经过次数有且仅有一次。

    这道题有点像,不过那道题是欧拉回路,这道题是欧拉路径罢了。

    啊啦,心路历程好像在上一篇博客里已经吐槽过啦。

    无非就是我考场上觉得这道题可以(tarjan)缩点然后遍历这条链,然后在遍历链的时候把环展开(你可真是个小机灵鬼),当然我失败了(事实证明,个人的创造虽然必不可少,但学习的路上也要借鉴前人的经验,站在巨人的肩膀上。

    还有就是我考试的时候一直觉得(T=2)(T=1)简单,因为我还没有想出来怎么给边定方向比较好(qwq)(难道你就真看不出来这是无向边?


    ►Code View

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<cstring>
    using namespace std;
    #define N 100005
    #define M 200005
    #define INF 0x3f3f3f3f
    #define LL long long
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f*x;
    }
    struct node{
    	int v,nxt,w/*边的编号*/;
    }edge[M<<1];
    int hd[N],cnt=1;//方便找反向边(异或1 
    void add(int u,int v,int w)
    {
    	edge[++cnt].v=v;
    	edge[cnt].w=w;
    	edge[cnt].nxt=hd[u];
    	hd[u]=cnt; 
    }
    
    int T,m,n;
    int fa[N],d[N],ind[N],st[M*10],tot;
    void Init()
    {
    	for(int i=1;i<=n;i++)
    		fa[i]=i;
    }
    int Find(int x)
    {
    	if(fa[x]==x) return x;
    	return fa[x]=Find(fa[x]);
    }
    void Union(int u,int v)
    {
    	u=Find(u),v=Find(v);
    	if(u<v) fa[u]=v;
    	else fa[v]=u;
    }
    void dfs(int u)
    {
    	//本来是:
    	//for(int i=hd[u];i;i=edge[i].nxt)
    	//但这里加了当前弧优化 让hd[]和i一起走 
    	while(hd[u])
    	{
    		int i=hd[u];
    		hd[u]=edge[i].nxt;
    		if(edge[i].w)
    		{//当前边的反向边没有被选 
    			int f=edge[i].w;
    			edge[i].w=0;
    			edge[i^1].w=0;//反向边不能再选 
    			//d[u]--;
    			//d[edge[i].v]--;度数只用于判断是否有解 后面没有实际影响 
    			dfs(edge[i].v);
    			st[++tot]=f;
    			
    		}
    	}
    	return ;
    }
    void solve1()
    {
    	for(int i=1;i<=m;i++)
    	{
    		int u=rd(),v=rd();
    		add(u,v,i);
    		add(v,u,-i);
    		d[u]++,d[v]++;
    		Union(u,v);
    	}
    	int flag=0;
    	for(int i=1;i<=n;i++)
    		if(d[i])
    		{//只要求每条边经过一次  "孤岛"没有影响 
    			if(!flag) flag=Find(i);
    			else if(flag!=Find(i))
    			{
    				puts("NO");
    				return ;
    			}
    		}
    	
    	int cnt=0,s=-1;
    	for(int i=1;i<=n;i++)
    		if(d[i]&1)
    			cnt++,s=i;
    	if(cnt!=2&&cnt!=0)
    	{
    		puts("NO");
    		return ;
    	}
    	for(int i=1;i<=n&&s==-1;i++)
    		if(d[i])
    			s=i;//回路的情况(0个奇点 
    	dfs(s);
    	puts("YES"); 
    	while(tot)
    		printf("%d ",st[tot--]);
    }
    void dfs2(int u)
    {
    	while(hd[u])
    	{
    		int i=hd[u];
    		hd[u]=edge[i].nxt;
    		if(edge[i].w)
    		{
    			int f=edge[i].w;
    			edge[i].w=0;
    			dfs2(edge[i].v);
    			st[++tot]=f;
    		}
    	}
    	return ;
    }
    void solve2()
    {
    	for(int i=1;i<=m;i++)
    	{
    		int u=rd(),v=rd();
    		add(u,v,i);
    		d[u]++,ind[v]++;
    		Union(u,v);
    	}
    	
    	int flag=0;
    	for(int i=1;i<=n;i++)
    		if(d[i]||ind[i])
    		{//判连通性 
    			if(!flag) flag=Find(i);
    			else if(flag!=Find(i))
    			{
    				puts("NO");
    				return ;
    			}
    		}
    		
    	int sta=0,ed=0;
    	for(int i=1;i<=n;i++)
    	{
    		if(d[i]==ind[i]) continue;
    		if(d[i]-ind[i]==1&&sta==0)
    		{
    			sta=i;
    			continue;
    		}
    		if(ind[i]-d[i]==1&&ed==0)
    		{
    			ed=i;
    			continue;
    		}
    		puts("NO");
    		return ;
    	}
    	for(int i=1;i<=n&&sta==0;i++)
    		if(d[i]) sta=i;//回路的情况 
    	dfs2(sta);
    	puts("YES");
    	while(tot)
    		printf("%d ",st[tot--]);
    }
    int main()
    {
    	freopen("merge.in","r",stdin);
    	freopen("merge.out","w",stdout);
    	T=rd(),n=rd(),m=rd();
    	Init();
    	if(T==1) solve1();
    	else solve2();
    	return 0;
    }
    /*
    2 5 10
    2 4
    2 3
    3 3
    5 2
    5 5
    5 3
    4 5
    4 3
    3 2
    4 5
    */
    
    
    
  • 相关阅读:
    数据结构课后
    idea 使用java 链接sqlservice 2008
    超链接 a href 提交表单通过post方式
    课程主页之课程接口
    课程主页之课程表数据
    课程表分析
    课程前端简单页面
    前台的登录注册
    ORM常用字段及参数与查询 -刘
    Celery配置与使用
  • 原文地址:https://www.cnblogs.com/lyttt/p/14030744.html
Copyright © 2011-2022 走看看