zoukankan      html  css  js  c++  java
  • hdu 3472 HS BDC 混合欧拉 网络流

    题意就是问能否将给定的几个单词全部连接起来,两个单词能连接是当前一个单词的最后一个字母等于后一个单词的首字母。还有一些单词反向也没有关系。

    建图,每输入一个单词,只看他的首尾字母,连接一条首字母到尾字母的有向边,如果他可以反向,那么再反向建立一条边,即该边是无向边。然后就是一个混合欧拉了。

    还有一个注意的地方,就是可能是欧拉道路,这时只要在添加一条边连接两个奇度节点就好。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    #define inf 100000
    const int maxn=100;
    int n,m;
    int p[50],in[50],out[50];
    int level[maxn],que[maxn];
    int head[maxn],lon;
    int min(int a,int b)
    {
        if(a<b) return a;
        else return b;
    }
    struct edge
    {
        int next,to,c;
    }e[200000];
    void edgeini()
    {
        memset(head,-1,sizeof(head));
        lon=-1;
    }
    void edgemake(int from,int to,int c)
    {
        e[++lon].c=c;
        e[lon].to=to;
        e[lon].next=head[from];
        head[from]=lon;
    }
    void make(int from,int to,int c)
    {
        edgemake(from,to,c);
        edgemake(to,from,0);
    }
    
    bool makelevel(int s,int t)
    {
        memset(level,0,sizeof(level));
        int front=1,end=0;
        que[++end]=s;
        level[s]=1;
        while(front<=end)
        {
            int u=que[front++];
            if(u==t) return true;
            for(int k=head[u];k!=-1;k=e[k].next)
            {
                int v=e[k].to;
                if(!level[v]&&e[k].c)
                {
                    que[++end]=v;
                    level[v]=level[u]+1;
                }
            }
        }
        return false;
    }
    
    int dfs(int now,int t,int maxf)
    {
        if(now==t||maxf==0) return maxf;
        int ret=0;
        for(int k=head[now];k!=-1;k=e[k].next)
        {
            int u=e[k].to;
            if(level[u]==level[now]+1&&e[k].c)
            {
                int f=dfs(u,t,min(e[k].c,maxf-ret));
                e[k].c-=f;
                e[k^1].c+=f;
                ret+=f;
                if(ret==maxf) return ret;
            }
        }
        if(ret==0) level[now]=0;
        return ret;
    }
    
    int maxflow(int s,int t)
    {
        int ret=0;
        while(makelevel(s,t))
        {
            ret+=dfs(s,t,inf);
        }
        return ret;
    }
    int find (int x)
    {
        if(x==p[x]) return x;
        else return p[x]=find(p[x]);
    }
    void link(int a,int b)
    {
        int fa=find(a);
        int fb=find(b);
        if(fa!=fb)
            p[fa]=fb;
    }
    int main()
    {
        char str[30];
        int cas;
        int s,t;
        int s1,s2;
        int sum=0;
        scanf("%d",&cas);
        while(cas--)
        {
            sum++;
            int i,j;
            int now;
            int len,flag,u,v,mk;
            for(i=1;i<=30;i++) p[i]=i;
            memset(in,0,sizeof(in));
            memset(out,0,sizeof(out));
            scanf("%d",&m);
            s=0;t=30;
            edgeini();
            for(i=1;i<=m;i++)
            {
                scanf("%s",str);
                len=strlen(str);
                scanf("%d",&mk);
                u=str[0]-'a'+1;
                v=str[len-1]-'a'+1;
                now=v;
                out[u]++;
                in[v]++;
                link(u,v);
                if(mk==1)
                    make(u,v,1);
            }
            int cnt=0;
            flag=1;
            s1=s2=-1;
            for(i=1;i<=30;i++)
            {
                if(in[i]||out[i])
                {
                    if(find(i)!=find(now))
                    {
                        flag=0;
                        break;
                    }
                    if((out[i]+in[i])%2==1)
                    {
                        cnt++;
                        if(s1==-1)s1=i;
                        else s2=i;
                    }
                }
            }
            if(cnt!=0&&cnt!=2) flag=0;
            if(flag==0)
            {
                printf("Case %d: Poor boy!
    ",sum);
                continue;
            }
            if(cnt==2)
            {
                out[s1]++;
                in[s2]++;
                make(s1,s2,1);
            }
            for(i=1;i<=30;i++)
            {
                if(out[i]-in[i]>0)
                     make(s,i,(out[i]-in[i])/2);
                else if(in[i]-out[i]>0)
                     make(i,t,(in[i]-out[i])/2);
            }
            int flow=maxflow(s,t);
            for(i=head[s];i!=-1;i=e[i].next)
            {
                if(e[i].c>0)
                    flag=0;
            }
            if(flag)printf("Case %d: Well done!
    ",sum);
            else printf("Case %d: Poor boy!
    ",sum);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Broadcom 43228 Kali Linux Ubuntu
    linux 栈空间查看和修改
    mininet 操作命令
    linux shell note
    进程与线程的区别
    JAVA基础--JAVA 集合框架(泛型、file类)
    HashMap的实现原理
    Java 流(Stream)、文件(File)和IO
    总结接口和抽象类的异同
    Java 泛型
  • 原文地址:https://www.cnblogs.com/vermouth/p/3839712.html
Copyright © 2011-2022 走看看