• 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
  • 相关阅读:
    linux(CENTOS)系统各个目录的作用详解
    2018 焦作E java 高精度暴力
    [SHOI2015]激光发生器,计算几何 直线相交
    codeforces 600E dfs+线段树合并
    2018 南京区域赛A SG打表
    8个常见的硬币博弈的SG值规律
    hdu 3389 阶梯博弈
    组合游戏与博弈好文
    gym 100500B 多项式哈希+Rabbin-Karp/最小表示法
    zjoi 2007 捉迷藏 动态点分治+可删堆
  • 原文地址:https://www.cnblogs.com/vermouth/p/3839712.html
Copyright © 2020-2023  润新知