zoukankan      html  css  js  c++  java
  • 组合「欧拉路」

    题目描述

    后缀为 contest/181/problem/1

    思路分析

    考试结束前30分钟才读懂题……每个单词有两个字符,其中第一个字符必须和当前的复杂词的结尾字符相同才能加上去,这不难想到需要建边。
    然后我就暴力跑了一遍,然后就没有然后了……
    其实就是一个欧拉路,将每一个简单词的两个字符之间建边,权值为该简单词的编号。
    (T=1) 的时候是无向图,(t=2) 的时候是有向图,分开讨论就好了

    关于欧拉路

    无向图和有向图能成为欧拉路的都分别有两种情况

    • 无向图:
      1.所有点的度数全部为偶数
      2.只有两个点的度数为奇数(起点和终点)
    • 有向图:
      1.所有点出度和入度均相同
      2.只有两个点出度和入度不同,且出度和入度的差值一个为 (1),另一个为 (-1)(起点和终点)

    如果是欧拉回路的话,那么无论是有向图还是无向图,都只有第一种情况成立

    (Code)

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define R register
    #define N 200010
    using namespace std;
    inline int read(){
    	int x = 0,f = 1;
    	char ch = getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	return x*f;
    }
    int t,m,n,x[N],y[N],head[N],ans[N],sta[N],top,in[N],out[N],tot,cnt;
    bool vis[N<<1],flag[N];
    struct edge{
    	int to,next,id;
    }e[N<<1];
    int len = 1;
    void addedge(int u,int v,int w){
    	e[++len].to = v;
    	e[len].id = w;
    	e[len].next = head[u];
    	head[u] = len;
    }
    void dfs(int u){
    	vis[u] = 1,cnt++;
    	for(R int i = head[u];i;i = e[i].next){
    		int v = e[i].to;
    		//printf("--%d--
    ",v);
    		if(vis[v])continue;
    		dfs(v);
    	}
    }
    void dfs1(int u,int x){
    	for(R int i = head[u];i;i = e[i].next){
    		if(vis[i])continue;
    		vis[i] = vis[i^1] = 1;
    		int v = e[i].to;
    		head[u] = i;//这里是个小技巧,可以避免多余的遍历,不加的话实测会T
    		dfs1(v,i);
    		i = head[u];
    	}
    	ans[++ans[0]] = e[x].id;
    }
    void solve1(){
    	for(R int i = 1;i <= n;i++){
    		x[i] = read(),y[i] = read();
    		if(!vis[x[i]])vis[x[i]] = 1,tot++;
    		if(!vis[y[i]])vis[y[i]] = 1,tot++;
    		addedge(x[i],y[i],i),addedge(y[i],x[i],-i);
    		in[x[i]]++,in[y[i]]++;
    	}
    	memset(vis,0,sizeof(vis));
    	dfs(x[1]);
    	//printf("%d %d
    ",cnt,tot);
    	if(cnt!=tot)return puts("NO"),void();
    	memset(vis,0,sizeof(vis));
    	for(R int i = 1;i <= n;i++){
    		if((in[x[i]]&1)&&!vis[x[i]])sta[++top] = x[i],vis[x[i]] = 1;
    		if((in[y[i]]&1)&&!vis[y[i]])sta[++top] = y[i],vis[y[i]] = 1;
    	}
    	memset(vis,0,sizeof(vis));
    	if(!top)dfs1(x[1],0);
    	else if(top==2)dfs1(sta[1],0);
    	else return puts("NO"),void();
    	puts("YES");
    	for(R int i = n;i;i--)printf("%d ",ans[i]);
    }
    void dfs2(int u,int x){
    	if(!flag[u])flag[u] = 1,cnt++;
    	for(R int i = head[u];i;i = e[i].next){
    		if(vis[i])continue;
    		vis[i] = 1;
    		int v = e[i].to;
    		head[u] = i;
    		dfs2(v,i);
    		i = head[u];
    	}
    	ans[++ans[0]] = e[x].id;
    }
    void solve2(){
    	for(R int i = 1;i <= n;i++){
    		x[i] = read(),y[i] = read();
    		if(!vis[x[i]])vis[x[i]] = 1,tot++;
    		if(!vis[y[i]])vis[y[i]] = 1,tot++;
    		addedge(x[i],y[i],i);
    		out[x[i]]++,in[y[i]]++;
    	}
    	memset(vis,0,sizeof(vis));
    	for(R int i = 1;i <= n;i++){
    		if(in[x[i]]!=out[x[i]]){
    			if(abs(in[x[i]]-out[x[i]])!=1)return puts("NO"),void();
    			if(!vis[x[i]])sta[++top] = x[i],vis[x[i]] = 1;
    		}
    		if(in[y[i]]!=out[y[i]]){
    			if(abs(in[y[i]]-out[y[i]])!=1)return puts("NO"),void();
    			if(!vis[y[i]])sta[++top] = y[i],vis[y[i]] = 1;
    		}
    	}
    	memset(vis,0,sizeof(vis));
    	if(!top)dfs2(x[1],0);
    	else if(top==2){
    		if(in[sta[1]]-out[sta[1]]==in[sta[2]]-out[sta[2]])return puts("NO"),void();
    		if(out[sta[1]]-in[sta[1]]==1)dfs2(sta[1],0);
    		else dfs2(sta[2],0);
    	}
    	else return puts("NO"),void();
    	if(cnt!=tot)return puts("NO"),void();
    	puts("YES");
    	for(R int i = n;i;i--)printf("%d ",ans[i]);
    }
    int main(){
    	freopen("merge.in","r",stdin);freopen("merge.out","w",stdout);
    	t = read(),m = read(),n = read();
    	if(t==1)solve1();
    	else solve2();
    	return 0;
    }
    
    
  • 相关阅读:
    读写excel的组件
    一个关于C#语言中的Property的低级BUG,花了我二十分钟
    使用wwAppConfiguration类库来轻松读写应用程序配置信息
    为因地震死难的同胞默哀
    页面执行时生成静态文件的方法
    【转载】sp_spaceused2,看库里全部表占用的物理空间
    在微软中文技术论坛 CSDN cnblogs 三个微软社区中提问
    在内网服务器中获得真正的客户端ip的方法
    深拷贝的通用方法
    你知道在word中如何将段落标记替换成其他字符吗?
  • 原文地址:https://www.cnblogs.com/hhhhalo/p/14015914.html
Copyright © 2011-2022 走看看