hdu3472 混合图判断欧拉通路

对于欧拉回路,先判断出度入度的差是否为偶数,然后最大流一次。

此题是判断有无欧拉通路,前提要判断图是否连通,然后欧拉通路的条件:要么出入度差没有奇数,或者只有2个点。

所以先统计差为奇数的个数,如果不为0或2,不可能。然后如果为2,表示可能使欧拉路,所以此时可以将这两个点相连,类似添加一条无向边。然后就是判断是否为欧拉回路了。

#include<stdio.h>
#include<string.h>
#include<queue>
#define maxn 50
#define INF 9999999
using namespace std;
struct node
{
    int to;
    int v;
    int flag;
    int next;
}edge[1000*1000];
char s[1002][25];
int vis[maxn],pre[maxn],index,in[maxn],out[maxn],n,sum,t,ff;
int pa[maxn];
int find(int x)
{
    if(pa[x]!=x)pa[x]=find(pa[x]);
    return pa[x];
}
void add(int x,int y,int z)
{
    edge[index].to=y;
    edge[index].v=z;
    edge[index].flag=index+1;
    edge[index].next=pre[x];
    pre[x]=index++;
    edge[index].to=x;
    edge[index].v=0;
    edge[index].flag=index-1;
    edge[index].next=pre[y];
    pre[y]=index++;
}
int dfs(int u,int low)
{
    int i;
    if(u==t)
        return low;
    for(i=pre[u];i!=-1;i=edge[i].next)
    {
        if(vis[edge[i].to]==vis[u]+1&&edge[i].v)
        {
            int a=dfs(edge[i].to,min(low,edge[i].v));
            if(!a)continue;
            edge[i].v-=a;
            edge[edge[i].flag].v+=a;
            return a;
        }
    }
    return 0;
}
int BFS()
{
    int i;
    queue<int>q;
    memset(vis,-1,sizeof(vis));
    vis[0]=0;
    q.push(0);
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        for(i=pre[t];i!=-1;i=edge[i].next)
        {
            if(vis[edge[i].to]<0&&edge[i].v)
            {
                vis[edge[i].to]=vis[t]+1;
                q.push(edge[i].to);
            }
        }
    }
    if(vis[t]>0)
        return 1;
    return 0;
}
void Dinic()
{
    int ans=0;
    while(BFS())
    {
        while(1)
        {
            int a=dfs(0,INF);
            if(!a)break;
            ans+=a;
        }
    }
    if(ans==sum)
       printf("Case %d: Well done!\n",++ff);
    else
        printf("Case %d: Poor boy!\n",++ff);
}
void slove(int fs)
{
    int i,st,se;//欧拉路奇数点的开始结束点
    st=se=-1;
    int count=0,flag=0;
    for(i=1;i<='z'-'a'+1;i++)
    {
        if(in[i]||out[i])
        {
            if(find(i)!=find(fs))
            {
                flag=1;
                break;
            }
            else if((out[i]-in[i])%2!=0)
            {
                count++;
                if(st==-1)st=i;
                else se=i;
            }
        }
    }
    if(count!=0&&count!=2) flag=1;

    if(flag)
        printf("Case %d: Poor boy!\n",++ff);
    else
    {
        if(count==2)
        {
            add(st,se,1);
            out[st]++;
            in[se]++;
        }
        for(i=1;i<='z'-'a'+1;i++)
        {
            if(out[i]>in[i])
            {
                add(0,i,(out[i]-in[i])/2);
                sum+=((out[i]-in[i])/2);
            }
            else if(in[i]>out[i])
            {
                add(i,t,(in[i]-out[i])/2);
            }
        }
        Dinic();
    }
}
int init()
{
    int i,fs;
    t='z'-'a'+2;
    sum=0;
    index=1;
    for(i=0;i<=30;i++)pa[i]=i;
    memset(pre,-1,sizeof(pre));
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        int z;
        scanf("%s %d",s[i],&z);
        int l=strlen(s[i]);
        int x=s[i][0]-'a'+1;
        int y=s[i][l-1]-'a'+1;
        in[y]++,out[x]++,fs=x;
        int fx=find(x),fy=find(y);
        if(fx!=fy)pa[fx]=fy;
        if(z)
        {
            add(x,y,1);
        }
    }
    return fs;
}
int main()
{
    ff=0;
    int t,father;
    scanf("%d",&t);
    while(t--)
    {
        father=init();
        slove(father);
    }
}

 

posted @ 2015-10-11 15:15  sweat123  阅读(240)  评论(0编辑  收藏  举报