`
暴风雪
  • 浏览: 390622 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

[并查集+混合图欧拉回路+网络流]hdoj 3472:HS BDC

阅读更多

大致题意:

    给出你n个单词,如果一个单词的尾部和另一个单词的头部相同那么这两个单词就能连在一起(比如‘abc’和‘cde’就能够连成abc-cde),如果这个单词后面的数字是1,则代表这个单词的逆序也是一个单词,可以翻转过来。求所有单词能不能连成一长串。

 

大致思路:
    转化为混合图的欧拉回路,把字母当作节点。注意要用并查集来检测图是否连通。

 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int inf=1<<30;
const int nMax=2000;
const int mMax=100000;

class node{
    public:
    int c,u,v,next;
};node edge[mMax];
int ne, head[nMax];
int cur[nMax], ps[nMax], dep[nMax];

void addedge(int u, int v,int w){   ////dinic邻接表加边
 //   cout<<u<<" add "<<v<<endl;
    edge[ne].u = u;
    edge[ne].v = v;
    edge[ne].c = w;
    edge[ne].next = head[u];
    head[u] = ne ++;
    edge[ne].u = v;
    edge[ne].v = u;
    edge[ne].c = 0;
    edge[ne].next = head[v];
    head[v] = ne ++;
}

int dinic(int s, int t){                       //  dinic
    int tr, res = 0;
    int i, j, k, f, r, top;
    while(1){
        memset(dep, -1, sizeof(dep));
        for(f = dep[ps[0]=s] = 0, r = 1; f != r;)
            for(i = ps[f ++], j = head[i]; j; j = edge[j].next)
                if(edge[j].c && dep[k=edge[j].v] == -1){
                    dep[k] = dep[i] + 1;
                    ps[r ++] = k;
                    if(k == t){
                        f = r; break;
                    }
                }
        if(dep[t] == -1) break;
        memcpy(cur, head, sizeof(cur));
        i = s, top = 0;
        while(1){
            if(i == t){
                for(tr =inf, k = 0; k < top; k ++)
                    if(edge[ps[k]].c < tr)
                        tr = edge[ps[f=k]].c;
                for(k = 0; k < top; k ++){
                    edge[ps[k]].c -= tr;
                    edge[ps[k]^1].c += tr;
                }
                i = edge[ps[top=f]].u;
                res += tr;
            }
            for(j = cur[i]; cur[i]; j = cur[i] =edge[cur[i]].next){
                if(edge[j].c && dep[i]+1 == dep[edge[j].v]) break;
            }
            if(cur[i]){
                ps[top ++] = cur[i];
                i = edge[cur[i]].v;
            }
            else{
                if(top == 0) break;
                dep[i] = -1;
                i = edge[ps[-- top]].u;
            }
        }
    }
    return res;
}

char str[30];
int in[nMax];
int out[nMax];
bool vis[nMax];

int p[nMax],r[nMax];
int find(int a){
    if(p[a]!=a){
        p[a]=find(p[a]);
    }
    return p[a];
}
void unionset(int i,int j){
    i=find(i);
    j=find(j);
    if(i!=j){
        if(r[i]>r[j]){
            p[j]=i;
        }
        else{
            p[i]=j;
            if(r[i]==r[j]){
                r[i]++;
            }
        }
    }
}

int main(){
    int i,j,k,cas,a,b,n,f,len,flag,s,t,sum;
    scanf("%d",&cas);
    for(int ii=1;ii<=cas;ii++){
        s=27,t=28;
        ne=2;
        flag=1;
        memset(head,0,sizeof(head));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(vis,0,sizeof(vis));
        for(i=0;i<100;i++)p[i]=i,r[i]=0;
        scanf("%d",&n);
        for(i=0;i<n;i++){
            scanf("%s%d",str,&f);
            len=strlen(str);
            in[str[len-1]-'a']++;
            out[str[0]-'a']++;
            vis[str[0]-'a']=vis[str[len-1]-'a']=1;
            unionset(str[len-1]-'a',str[0]-'a');
            if(f==1){
                addedge(str[0]-'a',str[len-1]-'a',1);
            }
        }
        printf("Case %d:",ii);
        for(i=0;i<26;i++){
            if(vis[i]){
                for(j=i+1;j<26;j++){
                    if(vis[j]){
                        if(find(i)!=find(j)){
                            flag=0;
                            break;
                        }
                    }
                }
                break;
            }
        }
        int v1=-1,v2=-1,tmp=0;
        for(i=0;i<26;i++){
            if(!vis[i])continue;
            if((in[i]-out[i])%2==1){
                v1=i;
                tmp++;
            }
            if((in[i]-out[i])%2==-1){
                v2=i;
                tmp++;
            }
        }
        if(tmp==0||(tmp==2&&v1!=-1&&v2!=-1)){
            if(tmp==2){
                addedge(v1,v2,1);
                in[v2]++;
                out[v1]++;
            }
        }
        else{
            flag=0;
        }
        if(!flag){
            printf(" Poor boy!\n");
            continue;
        }
        sum=0;
        for(i=0;i<26;i++){
            if(!vis[i])continue;
            tmp=(out[i]-in[i])/2;
            if(tmp<0){
                addedge(i,t,-tmp);
            }
            else if(tmp>0){
                sum+=tmp;
                addedge(s,i,tmp);
            }
        }
        if(dinic(s,t)!=sum){
            printf(" Poor boy!\n");
        }
        else{
            printf(" Well done!\n");
        }
    }
    return 0;
}
 
0
0
分享到:
评论

相关推荐

    欧拉回路的Fleury算法

    欧拉回路的Fleury算法 欧拉回路的Fleury算法是图论中...欧拉回路的Fleury算法是一种有效的算法,可以快速判断图是否存在欧拉回路,并可以输出其中一条欧拉回路。该算法广泛应用于图论、计算机网络、交通网络等领域。

    欧拉回路的构建及输出欧拉回路的路径

    这里以构建一个度全部相同的欧拉回路,并输出欧拉回路的路径 1.构建欧拉回路 连通主要是靠树来保证,首先建立一个度为k的完全图,其中会有很多需要主要的地方 (1)首先构造树 =&gt;保证顶点连通 (2)将度的点...

    欧拉回路C++程序(随机给图求欧拉回路)

    欧拉回路C++程序 随机输入任意点数,给出图中存在的欧拉回路

    欧拉回路输出路径

    这段代码提供了一个完整的解决方案,用于检测和输出欧拉回路,涵盖了图的构建、性质验证、并查集操作以及欧拉回路的经典算法。它不仅展示了数据结构的应用,如邻接表和并查集,还深入讲解了图论中的一个重要概念——...

    有向图的欧拉回路

    而欧拉回路则是在图中从一个顶点出发,经过每条边恰好一次,并最终返回到起点的路径。如果一个图存在欧拉回路,那么我们说这个图是欧拉图。 题目所提到的是针对有向图的欧拉回路的判断。在有向图中,边的方向决定了...

    欧拉回路程序java

    根据提供的文件信息,本文将对“欧拉回路程序java”进行详细解析,涉及的知识点主要包括:欧拉路径与欧拉回路的概念、Java程序设计基础、数据结构(如图和节点)、算法实现(欧拉回路算法)等。 ### 欧拉路径与欧拉...

    欧拉回路的实验报告

    通过递归的方式遍历图的每个顶点,尝试删除每条边并继续搜索,直至找到欧拉回路。 - **BFS (广度优先搜索)**:用于检查图是否连通。通过广度优先搜索,标记访问过的顶点,确保图是连通的。 #### 三、代码解析 - **...

    欧拉回路题集

    - **题目描述**:构建特定类型的图——德布鲁因图,并找出其欧拉回路。 - **解题思路**:构建德布鲁因图后,判断其是否存在欧拉回路。 - **数据结构**:邻接表。 5. **【HDU】1956 Sightseeing tour 混合欧拉** ...

    实验_38_如何构建欧拉回路.pdf

    在本文中,我们将了解如何构建欧拉回路,掌握用构造证明法证明定理2的充分条件,并采用定理2的方法编程给出三个图的欧拉回路。 欧拉回路的定义 欧拉回路(Eulerian Circuit)是一种图论中的概念,它是指在一个连通...

    3.仇荣琦《欧拉回路性质与应用探究》1

    例如,可以设计问题让参赛者找出一个图的欧拉回路,或者判断一个给定的图是否包含欧拉回路。解决这些问题通常需要运用图的遍历算法,如深度优先搜索(DFS)或广度优先搜索(BFS),并通过调整路径来确保每条边都被恰当地...

    oulahuilu.rar_欧拉回路

    欧拉回路是图论中的一个重要概念,它在计算机科学,特别是网络流、最短路径算法以及各种优化问题中有着广泛的应用。欧拉回路是指一个图中的简单路径,起点和终点相同,并且通过每条边恰好一次。简单来说,就是从图中...

    C语言求无向图欧拉回路例子

    自己用C写的无向图找欧拉回路的一个例子。主要用于数据结构的学习

    欧拉回路计算

    欧拉回路是图论中的一个重要概念,它指的是在无向图或有向图中,一个从某点出发,经过图中每条边恰好一次,最后又回到起点的路径。在学习数据结构的过程中,理解并实现欧拉回路的算法是一项基础而关键的任务。这个...

    Euler_difference.txt+前向欧拉法+后向欧拉法+中心差分法+matlab程序

    Euler_difference.txt+前向欧拉法+后向欧拉法+中心差分法+matlab程序

    欧拉回路的判定.rar

    本资源主要内容为有向图的无向图的欧拉回路的判定,使用的编程语言为JAVA,并采用邻接表作为图的存储结构,使用并查集判断图是否连通,利用图的遍历算法得到一条有效的欧拉回路,最后通过界面将欧拉路径动态显示在...

    有无向欧拉回路(邻接阵) template

    本文主要涉及图论中的一个经典问题——欧拉路径与欧拉回路的判定及其寻找算法,并着重介绍如何利用邻接矩阵来实现这一过程。 ### 欧拉路径与欧拉回路 在图论中,欧拉路径是指一条通过图中每条边恰好一次的路径,而...

    图论——欧拉路径和欧拉回路

    哈密尔顿回路关注的是在图中找到一个经过每个顶点恰好一次的路径,但它并不关心边的使用次数,而欧拉回路则强调每条边恰好被使用一次。 **四、寻找欧拉路径的方法** 1. **弗雷乌斯定理**:如果一个无向图包含两个...

    构造欧拉图与找欧拉回路的算法

    一个欧拉图是指一个无向图,其中每个边恰好被通过一次的路径,即从任一顶点出发,沿着边行走,最后能回到起点,且所有边都被走过一次,这样的路径被称为欧拉回路。如果一个图包含这样的路径,那么该图就被称为欧拉图...

    算法-欧拉回路(HDU-1878)(包含源程序).rar

    所谓欧拉回路,是一种在图中特定的路径,它从任意顶点出发,经过每条边恰好一次,并最终回到起点形成闭合回路。在计算机科学的应用中,欧拉回路涉及到多个领域,比如网络通信、数据结构优化、游戏开发中的路径规划等...

Global site tag (gtag.js) - Google Analytics