hdu3472(混合图欧拉路径判断)

来源:互联网 发布:淘宝联盟分享不了图片 编辑:程序博客网 时间:2024/05/18 01:46

链接:点击打开链接

题意:有n个单词,有的可以前后颠倒,看是否可以将n个单词首尾相连

代码:

#include <set>#include <queue>#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>using namespace std;const int INF=0x3f3f3f3f;struct node{    int u,v,cap;    node(){}    node(int u,int v,int cap):u(u),v(v),cap(cap){}}es[1005*1005];int R,S,T;int dis[1005],deg[1005],iter[1005];vector<int> tab[1005];void addedge(int u, int v, int cap){    tab[u].push_back(R);    es[R++]=node(u,v,cap);    tab[v].push_back(R);    es[R++]=node(v,u,0);}int bfs(){    int i,h;    queue<int> q;    q.push(S);    memset(dis,INF,sizeof(dis));    dis[S]=0;    while(q.size()){        h=q.front();        q.pop();        for(i=0;i<tab[h].size();i++){            node &e=es[tab[h][i]];            if(e.cap>0&&dis[e.v]==INF){                dis[e.v]=dis[h]+1;                q.push(e.v);            }        }    }    return dis[T]<INF;}int dfs(int x,int maxflow){    int flow;    if(x==T)    return maxflow;    for(int &i=iter[x];i<tab[x].size();i++){        node &e=es[tab[x][i]];        if(dis[e.v]==dis[x]+1&&e.cap>0){            flow=dfs(e.v,min(maxflow,e.cap));            if(flow){                e.cap-=flow;                es[tab[x][i]^1].cap+=flow;                return flow;            }        }    }    return 0;}int dinic(){    int ans,flow;    ans=0;    while(bfs()){        memset(iter,0,sizeof(iter));        while(flow=dfs(S,INF))        ans+=flow;    }    return ans;}int par[1005],sign[50];void init(int n){    int i;    for(i=0;i<=n;i++)    par[i]=i;}int found(int x){    if(par[x]==x)    return par[x];    return par[x]=found(par[x]);}void unite(int x,int y){    x=found(x);    y=found(y);    if(x==y)    return;    par[x]=y;}bool same(int x,int y){    return found(x)==found(y);}bool judge(){    int i,j;    for(i=1;i<=26;i++)    for(j=i+1;j<=26;j++)    if(sign[i]&&sign[j]&&(same(i,j)==0))    return 0;    return 1;}int main(){                                     //http://yzmduncan.iteye.com/blog/1149049    int n,i,j,t,c1,c2,st,en,cas,num,sum;        //这个讲的很详细    char s[55];    scanf("%d",&t);    for(cas=1;cas<=t;cas++){        scanf("%d",&n);        R=S=0,T=27;        init(26);        for(i=0;i<=T;i++)        tab[i].clear();        memset(deg,0,sizeof(deg));        memset(sign,0,sizeof(sign));        for(i=0;i<n;i++){            scanf("%s%d",s,&num);            c1=s[0]-'a'+1;            c2=s[strlen(s)-1]-'a'+1;            deg[c1]--,deg[c2]++;            sign[c1]=sign[c2]=1;            if(num)            addedge(c1,c2,1);            unite(c1,c2);        }        if(judge()==0){                         //并查集判断图是否联通            printf("Case %d: Poor boy!\n",cas);            continue;        }        sum=0;        st=en=-1;        for(i=1;i<=26;i++){                     //如果是存在欧拉路径而不是欧拉回路            if(deg[i]%2==1||deg[i]%2==-1){      //找出起点和终点并变成欧拉回路                if(deg[i]%2==1)                en=i;                else                st=i;                sum++;            }        }        if(sum==0||(sum==2&&st!=-1&&en!=-1))        addedge(en,st,1);        else{            printf("Case %d: Poor boy!\n",cas);            continue;        }        sum=0;        for(i=1;i<=26;i++){                     //因为每跑一条无向边两边的值相当于减2            if(deg[i]<0){                       //因此与源点汇点相连的点的值除二            sum+=(-deg[i]/2);            addedge(S,i,-deg[i]/2);            }            else if(deg[i]>0)            addedge(i,T,deg[i]/2);        }        if(sum==dinic())        printf("Case %d: Well done!\n",cas);        else        printf("Case %d: Poor boy!\n",cas);    }    return 0;}

0 0
原创粉丝点击