• poj 1386 判断欧拉图存在


    网上转载,有点偷懒

    //求欧拉回路,注意欧拉图的性质
    //构图的思想是以单词的首字母和末字母作为结点构图,将单词作为一条有向边
    //(A)----acm------>(M)-----malform---->(M)------mouse----->(E)
    //1、第一步是要先对图的连通性进行判断,即去掉边的方向,看图是否连通
    //我看了数据规模才26,我就偷懒写个Floyd水下算了
    //2、第二步就是根据欧拉图的性质进行判断就可以了,判断存在欧拉道路或存在欧拉回路
    //(1)有向图G为欧拉图(存在欧拉回路),当且仅当G的基图连通,且所有顶点的入度等于出度。
    //(2)有向图G为半欧拉图(存在欧拉道路),当且仅当G的基图连通,且存在顶点u的入度比出度大1、v的入度比出度小1,其它所有顶点的入度等于出度。
    #include<iostream>
    #include<vector>
    using namespace std;
    int indeg[26],outdeg[26],vis[26];
    int G[26][26];
    char word[1010];
    vector<int> letter;
    int t,m;
    bool checkEulerPath()
    {
    	int st,ed;
    	st = ed = 0;
    	bool circle = 1;
    	for(int i = 0;i < letter.size();++i)
    	{
    		int x = letter[i];
    		if(indeg[x] - outdeg[x] == 1)	
    		{
    			++ed;
    			circle = 0;
    		}
    		else if(outdeg[x] - indeg[x] == 1)	
    		{
    			++st;
    			circle = 0;
    		}
    		else if(outdeg[x] != indeg[x])	return false;
    	}
    	if(circle)	return true;
    	if(st == 1 && ed == 1)	return true;
    	return false;
    }
    void Floyd()
    {
    	for(int k = 0;k < 26;++k)
    		for(int i = 0;i < 26;++i)
    			for(int j = 0;j < 26;++j)
    				if(G[i][k] && G[k][j])	
    					G[i][j] = 1;
    }
    bool checkConnect()
    {
    	Floyd();
    	for(int i = 0;i < letter.size();++i)
    		for(int j = 0;j < letter.size();++j)
    		{
    			int x = letter[i];
    			int y = letter[j];
    			if(!G[x][y])	return false;
    		}
    	return true;
    }
    int main()
    {
    	//freopen("in.txt","r",stdin);
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d",&m);
    		letter.clear();
    		memset(indeg,0,sizeof(indeg));
    		memset(outdeg,0,sizeof(outdeg));
    		memset(G,0,sizeof(G));
    		memset(vis,0,sizeof(vis));
    		while(m--)
    		{
    			scanf("%s",word);
    			int last = word[strlen(word) - 1] - 'a';
    			int first = word[0] - 'a';
    			G[first][last] = G[last][first] = 1;
    			indeg[last]++;
    			outdeg[first]++;
    			if(!vis[last])	
    			{
    				letter.push_back(last);
    				vis[last] = 1;
    			}
    			if(!vis[first])
    			{
    				letter.push_back(first);
    				vis[first] = 1;
    			}
    		}
    		if(checkConnect() && checkEulerPath())	
    			printf("Ordering is possible.\n");
    		else 
    			printf("The door cannot be opened.\n");
    	}
    	return 0;
    }
    
  • 相关阅读:
    推导式
    解构
    for 循环
    运算符
    while 循环
    流程控制语句
    索引和切片
    ASC转换BCD,ASC2BCD(转)
    CString和char互转,十六进制的BYTE转CString
    C++添加简单的日记记录
  • 原文地址:https://www.cnblogs.com/steady/p/1942657.html
Copyright © 2020-2023  润新知