• poj 1386 欧拉回路


    题目的大意是,给出一些单词,问能否拼接成一串,使单词字母首尾相连。例如,Sample中的:
    acm
    malform
    mouse
    我们可以构造出:
    acm->malform->mouse,符合题目要求。
    明显,我们可以构造一个图来解决这个问题。以字母作为结点,则如果存在单词,例如acm,那么a和m就连一条边,同样,对于malform,我们就连一条环在m上。这个时候还可以统计点的出度和入度数。
    这是一个欧拉路问题,只要图中存在欧拉回路或者欧拉通路,都符合题目要求。关于判断一个图属否存在欧拉路或欧拉回路,有如下定理:

    定理 有向图G为欧拉图,当且仅当G的基图 连通,且所有顶点的入度等于出度。
    推论 有向图G为半欧拉图,当且仅当G的基图连通,且存在顶点u的入度比出度大1、v的入度比出度小1,其它所有顶点的入度等于出度。
    可以使用dfs判断图的连通性。

    因此,我们先必须通过dfs判断整个图是否连通,不连通就没戏了。连通后,再扫一次入度出度的情况即可。下面是代码:

    // 1386.cpp : 定义控制台应用程序的入口点。
    //思路要清晰,这样才能把题做出来。
    //欧拉回路
    #include "stdafx.h"
    
    
    #include<iostream>
    #include<cstring>
    using namespace std;
    
    const int N=26;
    typedef struct{
    	int in,out;
    }GRAPH;
    
    int v[N],linked;
    int g[N][N];
    
    void dfs(int index)//找出节点的个数。那么这里也可以用并查集做了呢。
    {                  //就是判断是不是连通。
    	v[index]=1;
    	for(int i=0;i<N;i++)
    		if(!v[i]&&g[i][index])
    			dfs(i);
    	linked++;
    }
    
    int main()
    {
    	int T,n,i,j;
    	char cmd[1005];
    	GRAPH degree[N];
    	scanf("%d",&T);
    	while(T--)
    	{
    		memset(degree,0,sizeof(degree));
    		memset(g,0,sizeof(g));
    		scanf("%d",&n);
    		while(n--)
    		{
    			int p1,p2;
    			scanf("%s",cmd);
    			int len=strlen(cmd);
    			p1=cmd[0]-'a';
    			p2=cmd[len-1]-'a';
    			degree[p1].out++;
    			degree[p2].in++;
    			g[p1][p2]=g[p2][p1]=1;
    
    		}
    		memset(v,0,sizeof(v));
    		int first=0,np=0;
    		for(i=0;i<N;i++)
    			if(degree[i].in||degree[i].out)
    			{
    				//if(!first)
    				first=i;//这里拿到第一个节点就行,不必要判断是不是非零!!!
    				np++;
    			}
    		linked=0;
    		dfs(first);
    		if(linked!=np)//np是有多少节点,linked也是,如果相等,则他们是连通的。
    		{
    			cout<<"The door cannot be opened."<<endl;
    			continue;
    		}
    		int na=0,nb=0,ne=0,nt=0;
    		for(i=0;i<N;i++)
    		{
    			if(degree[i].in==0&&degree[i].out==0)
    				continue;
    			nt++;
    			if(degree[i].in-degree[i].out==1)
    				na++;
    			else if(degree[i].in-degree[i].out==-1)
    				nb++;
    			else if(degree[i].in==degree[i].out)
    				ne++;
    
    		}
    		if(na==1&&nb==1&&ne==nt-2||ne==nt)//是欧拉回路的两个条件,要么是全部是一样的开始和结束字母,
    										 //要么是是有两个节点的入度和出度之差是一。
    			cout<<"Ordering is possible."<<endl;
    		else
    			cout<<"The door cannot be opened."<<endl;
    
    	}
    	system("pause");
    	return 0;
    }
    

      

  • 相关阅读:
    C#基础知识整理(一)c#语言基础—数据运算
    Socket 基于完整CS样式例子(转载)
    LVS NAT模式实战案例
    LVS DR模式实战案例
    Kubernetes 概述及Kubernetes各个组件概述
    k8s 基于kubeasz(ansible) 搭建高可用集群 kubernetes v1.22.2
    Linux LVS 介绍
    Python 读写字节数据(转)
    帮你克服web字体选择焦虑症
    python 深拷贝 浅拷贝
  • 原文地址:https://www.cnblogs.com/zhanglanyun/p/2115559.html
Copyright © 2020-2023  润新知