UVA 10129 Play on Words 欧拉回路(dfs)

来源:互联网 发布:五五开拉黑淘宝权 编辑:程序博客网 时间:2024/05/17 01:15

题目大意就是判断给你的每个单词是否能头尾相连成一串。


部分来自关于欧拉回路和欧拉路径 


定义:
欧拉回路:每条边恰好只走一次,并能回到出发点的路径
欧拉路径:经过每一条边一次,但是不要求回到起始点

①首先看欧拉回路存在性的判定:

一、无向图
每个顶点的度数都是偶数,则存在欧拉回路

二、有向图(所有边都是单向的)
每个节顶点的入度都等于出度,则存在欧拉回路

 三.混合图欧拉回路
  混合图欧拉回路用的是网络流。
  把该图的无向边随便定向,计算每个点的入度和出度。如果有某个点出入度之差为奇数,那么肯定不存在欧拉回路。因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路。
  好了,现在每个点入度和出度之差均为偶数。那么将这个偶数除以2,得x。也就是说,对于每一个点,只要将x条边改变方向(入>出就是变入,出>入就是变出),就能保证出 = 入。如果每个点都是出 = 入,那么很明显,该图就存在欧拉回路。
  现在的问题就变成了:我该改变哪些边,可以让每个点出 = 入?构造网络流模型。首先,有向边是不能改变方向的,要之无用,删。一开始不是把无向边定向了吗?定的是什么向,就把网络构建成什么样,边长容量上限1。另新建s和t。对于入 > 出的点u,连接边(u, t)、容量为x,对于出 > 入的点v,连接边(s, v),容量为x(注意对不同的点x不同)。之后,察看是否有满流的分配。有就是能有欧拉回路,没有就是没有。欧拉回路是哪个?查看流值分配,将所有流量非 0(上限是1,流值不是0就是1)的边反向,就能得到每点入度 = 出度的欧拉图。
  由于是满流,所以每个入 > 出的点,都有x条边进来,将这些进来的边反向,OK,入 = 出了。对于出 > 入的点亦然。那么,没和s、t连接的点怎么办?和s连接的条件是出 > 入,和t连接的条件是入 > 出,那么这个既没和s也没和t连接的点,自然早在开始就已经满足入 = 出了。那么在网络流过程中,这些点属于“中间点”。我们知道中间点流量不允许有累积的,这样,进去多少就出来多少,反向之后,自然仍保持平衡。
  所以,就这样,混合图欧拉回路问题,解了。


②.欧拉路径存在性的判定

一。无向图
一个无向图存在欧拉路径,当且仅当   该图所有顶点的度数为偶数   或者  除了两个度数为奇数外其余的全是偶数

二。有向图
一个有向图存在欧拉路径,当且仅当 该图所有顶点的度数为零     或者 一个顶点的度数为1,另一个度数为-1,其他顶点的度数为0

三。混合图欧拉路径
在混合图上也不例外,如何判断混合图欧拉回路问题的存在性呢?首先,我们用上文所说的方法判断该图是否存在欧拉回路,如果存在,欧拉路径一定存在。如果欧拉回路不存在,那么我们枚举欧拉路径的起点和终点,连接一条无向边,然后再用最大流判断是否存在欧拉回路即可。


欧拉回路 (dfs)

#include<cstring>#include<iostream>#include<cstdio>#include<cmath>#define N 30using namespace std;int vis[N], G[N][N] , n;void dfs(int u){    vis[u] = true;    for(int i=0; i<N; ++i)    {        if(G[u][i] && !vis[i])            dfs(i);    }}int main(){    int t, in[N],out[N];    char str[1005];    scanf("%d",&t);    while(t--)    {        memset(G, 0, sizeof(G));        memset(in, 0, sizeof(in));        memset(out, 0, sizeof(out));        scanf("%d",&n);        for(int i=1; i<=n; i++)        {            scanf("%s", str);            ++G[str[0]-'a'][str[strlen(str)-1]-'a'];            ++out[str[0]-'a'];            ++in[str[strlen(str)-1]-'a'];        }        bool flag=true;        int num1=0, num2=0;        for(int i=0; i<N; i++)        {            if(!flag) break;            if(in[i]!=out[i])            {                if(in[i]==out[i]+1)                {                    ++num1;                }                else if(out[i]==in[i]+1)                {                    ++num2;                }                else                {                    flag=false;                    break;                }            }        }        if(num1 && num2 && num1+num2>2) flag=false;        if(flag)        {            memset(vis, 0, sizeof(vis));            for(int i=0; i<N; i++)                if(out[i])                {                    dfs(i);                    break;                }            bool flag2=true;            for(int i=0; i<N; i++)            {                if(in[i] && !vis[i])                {                    flag2=false;                    break;                }                if(out[i] && !vis[i])                {                    flag2=false;                    break;                }            }            if(flag2) printf("Ordering is possible.\n");            else printf("The door cannot be opened.\n");        }        else        {            printf("The door cannot be opened.\n");        }    }    return 0;}



0 0
原创粉丝点击