zoukankan      html  css  js  c++  java
  • 【u008】瑞瑞的木棍

    Time Limit: 1 second
    Memory Limit: 128 MB

    【问题描述】

     瑞瑞有一堆的玩具木棍,每根木棍的两端分别被染上了某种颜色,现在他突然有了一个想法,想要把这
    些木棍连在一起拼成一条线,并且使得木棍与木棍相接触的两端颜色都是相同的,给出每根木棍两端
    的颜色,请问是否存在满足要求的排列方式。
      例如,如果只有2根木棍,第一根两端的颜色分别为red,blue,第二根两端的颜色分别为red,yellow,
    那么blue---red|red----yellow便是一种满足要求的排列方式。

    【输入格式】

    输入有若干行,每行包括两个单词,表示一根木棍两端的颜色,单词由小写字母组成,且单词长度不会超过10个字母,最多有250000根木棍。

    【输出格式】

    如果木棒能够按要求排列,输出Possible,否则输出Impossible

    Sample Input1

    blue red
    red violet
    cyan blue
    blue magenta
    magenta cyan
    

    Sample Output1

    Possible
    【题解】
    考的是hash函数。这里我们不去构造hash函数。而用字典树的方法来实现hash。即将单词这样的字符串转换为int类型。便于我们用下标访问。然后用木棍的信息建立一张图。即一根木棍就是一条边。然后需要连接起来。它的条件就是。这整张图为欧拉图。也就是一笔画。然后判断的方法是。
    1.图是联通的。
    2.统计所有的点的出度。如果出度全部为偶数或者恰好只有两个点为奇数。则可以一笔画。则能够把所有的木棍都连接起来。
    //联通的话用并查集也可以。用dfs从任意一个点进行搜索然后看下能不能走到所有的点。也可以。但是推荐用dfs,因为可以一边统计出度信息。
    然后如果不想打字典树。还有一种方法。就是把边的信息记录下来(记录的时候,两个字符串进行一下比较,小的放前面)。然后对边的信息进行排序。以边的左端点作为关键字排序。然后左端点相同的边就会紧邻在一起。我们把字符串编号一下就可以,然后还是一样建图即可。。
    【代码】
    #include <cstdio>
    #include <cstring>
    
    struct tree//用字典树的方法来获取某个单词的hash值。
    {
    	int hash;
    	int next[27];
    };
    
    int tot = 0, ne[500001], first[500001], en[500001], totm = 0, chudu[500001] = { 0 },temp_tot,tot_v=1;
    //用邻接表来存储图的信息。
    bool visited[500001] = { 0 };
    tree a[800001]; //用数组来模拟链表。
    
    int sear_ch(char s[50])//用字典树。来获取s这个字符串对应的hash值。
    {
    	int l = strlen(s);//获取字符串的长度。
    	int p = 1;//从根节点开始往下走
    	for (int i = 1; i <= l; i++)
    	{
    		int x = s[i - 1] - 'a' + 1;//把小写字母和数字1..26对应
    		if (a[p].next[x] == 0)//如果这个节点不存在。则新建一个节点、
    		{
    			tot_v++;
    			a[p].next[x] = tot_v;
    		}
    		p = a[p].next[x];//一直往下走。
    	}
    	if (a[p].hash == 0)//如果这条路径(这个字符串)之前没人走过,则给其一个新的hash值
    		a[p].hash = ++tot;
    	return a[p].hash;//然后直接返回这个值就可以了。。
    }
    
    void add(int x, int y)//加一条从x指向y的边
    {
    	totm++;
    	ne[totm] = first[x];//邻接表用的是链式存储的方式。
    	first[x] = totm;
    	en[totm] = y;
    }
    
    void dfs(int now)//这个程序会从最后一个点开始进行dfs看一下能不能走遍所有的点。
    {
    	temp_tot--;//找到了一个点,点的数目就减少。最后看temp_tot是否为0
    	visited[now] = true;
    	int temp = first[now];
    	while (temp != 0)//用邻接表来获取这个点的出度。
    	{
    		chudu[now]++;//顺便记录出度
    		int y = en[temp];
    		if (!visited[y])//如果没有访问过就访问。
    			dfs(y);
    		temp = ne[temp];//寻找下一个出度
    	}
    }
    
    int main()
    {
    	char s1[50], s2[50];
    	while (scanf("%s%s", s1, s2) != -1)//多行输入
    	{
    		int x, y;
    		x = sear_ch(s1);
    		y = sear_ch(s2);
    		add(x, y);
    		add(y, x);
    	}
    	temp_tot = tot;//用来递减的temp
    	if (tot>0) //如果什么都没输入也算是可以的。
    		dfs(tot);
    	if (temp_tot != 0)//如果图是不连通的则不能一笔画
    	{
    		printf("Impossible");
    		return 0;
    	}
    	int oushu = 0, jishu = 0;//统计奇数的出度和偶数的出度的个数。
    	for (int i = 1; i <= tot; i++)
    		if ((chudu[i] % 2) == 0)//其实只要统计奇数的出度的个数就可以了。
    			oushu++;
    		else
    			jishu++;
    	if (jishu == 0 || jishu == 2)//可以看到只要统计奇数的出度个数就可以。。
    		printf("Possible");
    	else
    		printf("Impossible");
    	return 0;
    }



  • 相关阅读:
    韩寒做错了(update 4 12)。
    放弃IE6。
    阿弥陀佛,我没有“抄袭”。
    婚姻。
    爆牙齿饭否?
    地震之后——和妈妈对话。
    8年前,《西班牙,我为你哭泣。》
    在等决赛中提问。
    地震之后——中国互联网在黑夜中哭泣。
    年轻。
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632299.html
Copyright © 2011-2022 走看看